主页 SwiftUI Chapter 5 Study Summary
Post
Cancel

SwiftUI Chapter 5 Study Summary

Preface

This article carries strong personal sentiment. If it makes you uncomfortable, please close it as soon as possible. This article is only for personal study records. Reprinting or sharing within the scope of the license is also welcome. Please respect the copyright and keep the original link. Thank you for your understanding and cooperation. If you find this site helpful, you can subscribe via RSS. Thanks for your support!

The SwiftUI Course

I’ve been persisting in learning SwiftUI recently. Over the weekend, when I had free time, I finished Chapter 4. What I mean by “watching” is hands-on practice plus tutorial study. Let me record some content that’s easy to forget.

Main Contents

  • Handling the TabBar transparency issue
  • Handling unit formatting issues

The TabBar Transparency Issue

After building various UIs with SwiftUI, I found that the TabBar view was being obscured,

and you need to use the following function applyTabbarBackground() when the app launches.

import SwiftUI

@main
struct AppEntry: App {
    init() {
        applyTabbarBackground()
    }
    
    var body: some Scene {
        WindowGroup {
            HomeScreen()
        }
    }
    
    func applyTabbarBackground() {
        let tabbarAppearence = UITabBarAppearance()
        tabbarAppearence.configureWithTransparentBackground()
        tabbarAppearence.backgroundColor = .secondarySystemBackground.withAlphaComponent(0.3)
        tabbarAppearence.backgroundEffect = UIBlurEffect(style: .systemChromeMaterial)
        UITabBar.appearance().scrollEdgeAppearance = tabbarAppearence
    }
}

Handling Unit Formatting Issues

The iOS system provides an internationalized unit class, Measurement, to handle units like grams, g, pounds, etc.

1
2
3
4
5
6
7
var desciption : String {
        let preferredUnit = Unit.getPreferredUnit(from: store)
        let measureMent = Measurement(value: wrappedValue, unit: unit.dimension)
        let converted = measureMent.converted(to: preferredUnit.dimension)
//        return converted.formatted(.measurement(width: .abbreviated, usage: .asProvided, numberFormatStyle: .number.precision(.fractionLength(0...1))))
        return converted.value.formatted(.number.precision(.fractionLength(0...1))) + " " + preferredUnit.localizedSymbol
    }

Here I recommend checking out the official WWDC20 video Formatters: Make data human-friendly

The video introduces tools that can format data such as dates, units, numbers, and text according to the user’s Locale.

Summary

Actually, Chapter 5 talks a lot about the high-level wrapping of property wrappers. I think the content is too long; rather than me recording it here, it’s better if you watch the tutorial video yourself — the explanations are quite thorough.

Secondly, a large portion covers unit testing. Since I’m not too keen on writing unit tests myself, I’ll skip it directly…

I’ve been following this course and hope to gain something from it. Below are the course materials I’ve organized. Please take a look.

SwiftUI Introductory Course

Place the related files of SwiftUI 入門課程 here, along with related links and further reading for each chapter.

Chapter 1: Basic Introduction

Introduces the Xcode interface and the basic architecture of SwiftUI.


Chapter 2: Layout

Practice layout and basic code refactoring.


Chapter 3: Property Wrappers

Introduces the commonly used property wrappers in SwiftUI: State, Binding, and Environment; practices creating lists and forms, and uses enums to organize code.

  • EnvironmentValues environment variables
  • The “in a result builder, local variables are treated as the block being built” mentioned in the video — you can learn more in this evolution proposal. Under the section The result builder transform, you can learn how result builders judge different statements.

Chapter 4: Data Persistence

Introduces iOS’s native data persistence methods and the concept of encoding, and implements a settings screen that uses AppStorage to store Boolean, enum, and Array data.


Chapter 5: Testing

Introduces basic testing concepts, Xcode’s testing interface, implements a test, and uses Measurement for unit conversion and displaying localized unit strings according to the user’s Locale.

  • WWDC20: Localized formatting tools, the video introduces tools that can format data such as dates, units, numbers, and text according to the user’s Locale.
  • WWDC19: Introduction to Testing, Test Plans, and CI/CD
  • Understanding Locale — Locale doesn’t refer only to language, but combines language and region to provide more precise conventions. For example, even in the same English language, the order of writing dates still differs between countries.
    • If your app doesn’t support other languages yet, Locale will be set to your project’s base language. For a detailed introduction, see this article, which also provides methods for getting the user's preferred / currently used language. Before you do localization, you can try getting these values to force-modify the Locale.
  • Adding a background color to the toolbar in iOS 16: the article focuses on the TabBar, but this toolbarBackground modifier can also modify the Navigation Bar.
  • You might notice that the TabBar looks different before iOS 14 🥲. If you want to unify it, you can refer to the code in this article to make the changes.

Chapter 6: Network Calls

Introduces basic networking concepts and further applications of Codable, and builds a new project that integrates The Cat API. The implementation of the new project includes:

  • Creating a Manager dedicated to handling networking.
  • Handling errors and showing alerts.
  • Observing reference types using ObservableObject.
  • Infinite Scroll that automatically loads more content.
  • Understanding the difference between the .task modifier and creating a new Task.
  • 6-2 Common HTTP status codes
  • 6-2 MIME type name lookup
  • 6-2 Flowchart for deciding whether to use cached data
  • 6-3 The conditions for adding a response to the cache mentioned in the video
  • 6-5 The website for quickly generating JSON parsing code used in the video. Remember, when using auto-generated code, always double-check it yourself, no matter how simple the data is.
  • 6-8 StateObject documentation: this document briefly introduces the three property wrappers used with ObservableObject and their update timing. I suggest reading the init and update parts; come back to it when you encounter StateObject being initialized repeatedly or not updating as expected.
  • 6-8 If you have doubts about the difference between StateObject and ObservedObject, refer to onevcat’s this article.
  • 6-11 The difference between onAppear and the task modifier. I think the differences mentioned in this article are all quite important; besides what’s mentioned in the video, it also covers using task with an id.
  • 6-11 If you’re unsure about when to use Task and Task.detached, refer to the When to use unstructured tasks and When to use detached tasks sections of this article.
    Additionally, the mainstream approach nowadays is to avoid using detached — not because it’s bad, but because there’s no strong reason to use it (i.e., no need to make your code more complex). However, I personally feel that detached’s explicitness is very helpful for initially understanding what your code does, and the errors and warnings arising from its lack of inheritance are also helpful for early learning.
  • 6-11 If you want to learn more about when onAppear fires, check out this article on View lifecycle.
  • 6-11 As mentioned in the video, ObservableObject puts the entire View on the MainActor. This article explains in detail the mysterious @MainActor situation of View structs. Once again, I don’t think you need to worry too much about this; when you encounter this error, just move it into the MainActor.
该博客文章由作者通过 CC BY 4.0 进行授权。