Day12 SwiftUI 05 - Life Cycle - SwiftUI App

Life Cycle - SwiftUI App

如前面所介绍的,在Xcode 12 创建新的 SwiftUI 专案视窗,在初始配置有一个改变,就是多了 Life Cycle 选单,前面我们新增过 UIKit App Delegate 的专案了,这边我们就来新增看看 SwiftUI App 的专案

https://ithelp.ithome.com.tw/upload/images/20210927/20118479DLl7PRCbBw.png

新建完成後,我们来看一下它自动产生的档案,来跟前面的 Life Cycle - UIKit App Delegate 专案比较,发现专案没有 AppDelegateSceneDelegate来处理 App 的生命周期及其各种状态了,代替的是一个与专案名字相同的档案,加上 "App" 後缀,例如HelloWorldApp.swift 档案:

https://ithelp.ithome.com.tw/upload/images/20210927/20118479H7gGXaD7ym.png

我们来看看这些修改做了些什麽

  • App 的 entry point 是采用 App 框架的结构 (structure),这是一种全新的型别,根据 Apple 官方文件,「App是一种协定,代表了 App 的结构和行为」,它取代了原本的 AppDelegate,并接管了它的许多功能
  • HelloWorldApp.swift 中 HelloWorldApp struct 被加了 @main 属性标记,以表示这是 App 的 entry point,而且不可能会有多於一个结构被这样标记,它将在调用时初始化应用程序
  • 结构的 body 型别为 Scene,这是另一个协定,根据官方文件,它是一个要显示给使用者的视图层次结构 (view hierarchy) 的容器。每个场景都包含视图层次结构的根视图,并具有由系统管理的生命周期
  • WindowGroup 是一个包装视图的场景,它是一个跨平台的结构,代表一个多窗口的场景,你可以在 macOS、iOS 等上使用它,它是你的应用程序视图层次结构的容器
  • 在 WindowGroup 中,需要为应用程序声明第一个视图,而我们要呈现的视图ContentView 是一个View,而不是一个场景,WindowGroup 使我们可以将它们包装到SwiftUI 可以识别和显示的单个场景中

SwiftUI 将整个原有的平台差异部分抽象为 App 和Scene,对於一个mac/iOS/iPad/watch/tv/..应用程序来说,App 代表了整个应用,Scene 代表了与Window 相关的多窗口,有些设备只有一个Scene 有些则有多个,虽然不同的OS 确实存在差异,但是在语义层面达到了一致

以下我们再对 SwiftUI App 或 SwiftUI App Lifecycle 做进一步的介绍

  1. App States Callbacks

    在 iOS 14 中,Apple 提供了 ScenePhase 来追踪应用程序的状态。 场景的状态在环境中被追踪,因此我们创建了 @Environment 属性来访问当前值,然後使用 onChange(of:) 修饰符来监听状态的任何变化。

    @main
    struct HelloWorldApp: App {
        @Environment(\.scenePhase) var scenePhase
    
        var body: some Scene {
            WindowGroup {
                ContentView()
            }.onChange(of: scenePhase) { (newScenePhase) in
                switch newScenePhase {
                case .background:
                    print("App State : Background")
                case .inactive:
                    print("App State : Inactive")
                case .active:
                    print("App State : Active")
                @unknown default:
                    print("App State : Unknown")
                }
            }
        }
    }
    
    

    有关更多详细信息,请参考官方文件

  2. Deeplink URLs

    在 UIKit 方法中,我们通过在AppDelegate 中 回调application(_:open:options:)方法处理所有深层链接 url,但是在 SwiftUI 中,我们可以通过将 onOpenURL 修饰符附加到应用程序的最顶层场景来处理传入的 url。 它在闭包中返回传入的 url

                ContentView()
                    .onOpenURL(perform: { url in
                        print("Incoming url: \(url)")
                    })
    
  3. App Init

    对於基本初始化,可以像在 AppDelegate 的 didFinishLaunchWithOptions 方法中一样执行初始化,或者如果您正在使用某些第三方并且需要在应用程序启动时进行设置, SwiftUI App 换在 struct HelloWorldAppinit 方法中进行初始化操作

    范例:

    @main
    struct HelloWorldApp: App {
        @Environment(\.scenePhase) var scenePhase
    
        init() {
            // perform any task on app launch
        }
    
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .onOpenURL(perform: { url in
                        print("Incoming url: \(url)")
                    })
            }.onChange(of: scenePhase) { (newScenePhase) in
                switch newScenePhase {
                case .background:
                    print("App State : Background")
                case .inactive:
                    print("App State : Inactive")
                case .active:
                    print("App State : Active")
                @unknown default:
                    print("App State : Unknown")
                }
            }
        }
    }
    
  4. AppDelegate in SwiftUI

    如果您有一些需求一定要用到 AppDelegate 的话,那麽 SwiftUI 提供了一种通过使用 @UIApplicationDelegateAdaptor 在 SwiftUI 生命周期内使用 AppDelegate 的方法

    @UIApplicationDelegateAdaptor提供了使用 UIApplicationDelegate 方法的选项,这些方法通常在 UIKit 应用程序中使用

    首先添加一个文件来创建 AppDelegate 类别,例如创建一个"MyAppDelegate.swift"後,里面内容为 "MyAppDelegate" 类别,它继承自 "UIResponder" 并有实作 "UIApplicationDelegate" 协定,然後添加didFinishLaunchWithOptions方法

https://ithelp.ithome.com.tw/upload/images/20210927/20118479lIe3jKJvH2.png

创建 AppDelegate 後,现在通过 @UIApplicationDelegateAdaptor 属性包装器将其附加到结构 "HelloWorldApp" 的入口点

https://ithelp.ithome.com.tw/upload/images/20210927/20118479KUm9rU0fRd.png

在调用场景 init 方法後,即会调用 AppDelegate 的 didFinishLaunchWithOptions方法。

以上就简单介绍了关於新的 SwiftUI 生命周期更新的基础

参考文件:Bye Bye AppDelegate! SwiftUI App Life Cycle


<<:  Day 12 - Spring Boot & MyBatis

>>:  Day12 开发插件 - 范例程序码介绍01 Flutter 端

Log Agent - Fluent Bit 简介

前几篇讲这麽多, 来介绍一个服务Fleunt Bit Fleunt Bit 它是一个开源的数据收集器...

Day 10:云端服务

前言 云端服务层级可分为三种: SaaS(软件即服务):提供给一般用户或商务使用的软件,如:Goog...

[Day 29] 永和美食纪录-和陞屋牛排

前言 转眼间食记已经来到了倒数第二篇,不晓得这些日子以来笔者推荐的美食有没有读者去试过了呢?不过美食...

[Day 23] props

这篇学的有点久,一直搞不懂他的概念是怎样,经过我一番的努力,终於把他搞懂了!!希望大家看完我这篇也可...

【Day31】新加坡工作後续的时程

Update(01/10):EP approved! 在这边纪录一下这份 offer 的各个时程。...