SwiftUI App Structure

SwiftUI 与传统的 UIKit 思路不同,是一种声明式 UI 框架,这种框架的特点就是摒弃了传统开发的代码按生命周期进行的流程概念,直接通过声明所呈现的内容来与用户进行交互。

App

swift 复制代码
protocol App

App 代表了应用程序的抽象,需要在它的 body 属性中声明应用所能够呈现的内容:

swift 复制代码
@main 
struct MyApp: App { 
    var body: some Scene { 
        WindowGroup { 
            Text("Hello, world!") 
        } 
    } 
}

在你的自定义实现结构体声明之上添加 @main,用来标记这是应用程序的唯一主入口。同时,这也意味着你的应用程序只能有这一个主入口。

Scene

App 的 body 属性中,可以组合一个或多个 Scene 的实现,每一个 Scene 实现包含视图结构的根视图,代表用户界面中的内容,也可能是一部分(多窗口),它的生命周期由系统管理。

SwiftUI 提供了一些 Scene 的实现来表示场景的场景,包括显示设置或是文档。 你也可以自定义创建 Scene,但其实就是组合一些系统提供的 Scene:

swift 复制代码
struct MyScene: Scene {
    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
    }
}

Scene 有一些常见实现:

  • WindowGroup
  • Settings
  • Window
  • ImmersiveSpace
  • DocumentGroup
  • ...

SwiftUI 是跨平台框架,所以基于不同的平台支持的 Scene 也有所不同。例如,visionOS 不支持 Window,而 ImmersiveSpace 是 visionOS 独有的。

App 的 body 中可以容纳一个或多个 Scene:

swift 复制代码
@main
struct Mail: App {

    var body: some Scene {
        WindowGroup {
            MailViewer()
        }
        Settings {
            SettingsView() 
        }
    }
}

应用启动,会默认打开第一个 Scene 所呈现的内容 。针对不同的平台,可能需要修改 plist 来支持多场景。例如,在 visionOS 平台或 iPadOS,需要添加 Enable Mutiple Windows 为 YES。

Scene 本质上就是呈现 View 结构的容器,系统会决定他们的显示行为,例如,在 iPadOS 或 macOS 支持多窗口,用户就可以创建或是删除一些窗口;而在 iOS 平台(or 其他)当应用处于活跃状态,视图内容将会占满整个屏幕。

Scene 的生命周期

可以通过环境值 scenePhase 来从 Scene 或 View 中读取当前 Scene 是否处于活跃状态:

swift 复制代码
struct MyScene: Scene {
    @Environment(\.scenePhase) private var scenePhase


    // ...
}

scenePhase 是枚举类型 ScenePhase,包括:

  • background:处于后台,不可交互;
  • inactive:处于前台,不可交互;
  • active:处于前台,可以交互。

Scene 提供了一些方法,可以对 Scene 进行配置,例如可以使用 onChange(of:perform) 来监听某个值的变化,从而触发一些操作,下面是一个当应用进入后台后清除缓存的操作:

swift 复制代码
struct MyScene: Scene {
    @Environment(\.scenePhase) private var scenePhase
    @StateObject private var cache = DataCache()


    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
        .onChange(of: scenePhase) { newScenePhase in
            if newScenePhase == .background {
                cache.empty()
            }
        }
    }
}

Scene 之间的通信

多个 Scene 可以通过在 App 中声明一些状态来进行通信。例如,使用 @StateObject 来初始化一个数据类,然后将数据类作为 ObservedObject 或通过环境作为 EnvironmentObject 提供给 Scene:

swift 复制代码
@main
struct Mail: App {
    @StateObject private var model = MailModel()


    var body: some Scene {
        WindowGroup {
            MailViewer()
                .environmentObject(model) // Passed through the environment.
        }
        Settings {
            SettingsView(model: model) // Passed as an observed object.
        }
    }
}

总结

SwiftUI App 以 App 协议的实现为应用主入口,其 body 属性中可以配置多个 Scene,App 启动时默认打开第一个 Scene。 Scene 代表用户界面的容器,用来承载视图结构,其内容是视图结构的根视图。Scene 具有生命周期,包括三种:

  1. backgroud
  2. inactive
  3. active 可以通过环境属性 scenePhase 来查询。 Scene 直接可以通过在 App 中定义共享的数据结构来共享数据。可以通过一些方法或通过参数的形式传递到不同的 Scene。
相关推荐
恋猫de小郭8 小时前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
靴子学长1 天前
iOS + watchOS Tourism App(含源码可简单复现)
mysql·ios·swiftui
hxx2217 天前
iOS swift开发系列--如何给swiftui内容视图添加背景图片显示
ios·swiftui·swift
胖虎18 天前
SwiftUI - (十九)组合视图
ios·swiftui·swift·组合视图
davidson14718 天前
Xcode
ios·swiftui·xcode·swift·apple
大熊猫侯佩9 天前
苹果开发者入门:修复 SwiftUI 中“跑偏的”动画(下)
swiftui·动画·animation·transition·转场·显式隐式动画·布局坐标
_rufeng_14 天前
SwiftUI入门篇
ios·swiftui·swift
大熊猫侯佩17 天前
SwiftUI 列表(或 Form)子项中的 Picker 引起导航无法跳转的原因及解决
list·swiftui·form·列表·navigation·导航·picker
袁代码1 个月前
SwiftUI开发教程系列 - 第十二章:本地化与多语言支持
开发语言·前端·ios·swiftui·swift·ios开发
袁代码1 个月前
SwiftUI开发教程系列 - 第1章:简介与环境配置
开发语言·ios·swiftui·swift·ios开发