SwiftUI是构建应用程序的好方法。简单,简洁,快速。可以用一半的代码行在SwiftUI中重新创建UIKit中的内容。以前需要数周才能完成的工作现在只需几个小时。但是直到今天,它还是有一个严重的缺点:它依赖于UIKit。
要显示使用SwiftUI创建的视图,您必须将其包装在UIHostingController中,该包装必须包装在UIWindow中,而UIWindow必须在SceneDelegate中定义:
对于为简化和性能而设计的框架,所有这些代码都没有意义。为什么只写30行代码来定义一个视图?
今天,在WWDC20上,宣布了一个解决方案:App。 App协议。说了这么简单,听起来很奇怪。
在Xcode 11.5之前的Xcode 12 Beta中,创建SwiftUI应用时,您会看到一个新选项:“ SwiftUI应用”。
什么,Apple是否在尝试向Xcode添加回显生成器?并非如此-实际上,这是“生命周期”的两个选项之一:

“生命周期”指的是应用程序的状态-通常沿“活动”,“非活动”或“背景”行。我们使用它来在启动时显示用户界面,并在退出时保存用户数据。
以前,这是在AppDelegate和SceneDelegate中处理的,这使管理应用程序状态变得很麻烦-它分散在两个文件中,是不是有些荒谬!
如果您选择“ SwiftUI App”并创建项目,则会注意到AppDelegate和SceneDelegate都消失了!相反,名为<App Name> App的文件将替换它们!

import SwiftUI
@main
struct HelloWorldApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
怎么样?苹果用17行(包括注释)替换两个完整的代码文件的工作。尽管“生命周期”事件听起来很重要,但是大多数人只会触摸AppDelegate或SceneDelegate一次或两次。代码清除,状态更改和大多数其他重要事件将自动处理。您无需为此担心。和保存数据?一个好的应用程序可以节省时间-而不是生命周期的尽头。您真正需要手动修改的生命周期中的唯一部分是入口点。 Xcode需要知道您要显示的内容。
苹果公司对App协议所做的事情就是将生命周期缩减到最重要的单个要素–切入点。每个其他生命周期都是可选的,您可以在以后添加。
无论如何,如果您熟悉SwiftUI,我们的入口点语法就不是什么新鲜事物了。它在struct中声明,在提高性能的同时还使其易于阅读。
以下面的代码为例,该代码呈现一些文字“ Hello World!”
struct ContentView: View {
var body: some View {
Text("Hello world!").padding()
}
}
它看起来非常类似于我们的HelloWorldApp结构!但是有一些区别:
@main告诉Xcode,以下结构HelloWorldApp将成为应用程序的入口点。此属性只能标记一个结构。
根据文档,App是一种协议,“表示应用程序的结构和行为”。 HelloWorldApp符合此要求。就像您的应用程序的基本视图一样,不,应用程序本身。您实际上是在写出此结构中的应用程序外观。
场景— SwiftUI视图的主体必须为View类型。同样,SwiftUI应用的主体必须为Scene类型。
等一下它不是App类型的吗?好吧,实际上,Scene在这里更有意义
每个场景都包含视图层次结构的根视图,并具有由系统管理的生命周期
场景就像是您的视图的容器,并会自动为您管理:
“系统会根据平台的状态并取决于应用程序的当前状态,决定何时以及如何在用户界面中显示视图层次结构。” -苹果开发商
而且,由于macOS和iPadOS等平台支持多个窗口,因此将所有应用程序视图包装在一个场景中将使可重用性变得更加容易,同时还允许包括活动状态,非活动状态和背景状态的“场景阶段”。
WindowGroup是一个包装视图的场景。我们要呈现的视图ContentView是一个View,而不是一个场景。 WindowGroup使我们可以将它们包装到SwiftUI可以识别和显示的单个场景中。
这就是所有新语法!
但是,如果您需要观察那些可选的生命周期事件,例如用户退出应用程序时该怎么办?在旧的SceneDelegate中,它看起来像这样:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
...
lots more code
...
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
print("scene is now active!")
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
print("scene is now inactive!")
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
print("scene is now in the background!")
}
}
虽然还算不错,但是每个生命周期事件都有单独的功能,因此我们的代码难以管理。
在新的App协议中,Apple确保即使生命周期中的可选部分(很少使用的部分)仍然非常容易实现:
我们首先创建一个ScenePhase属性,该属性从系统获取活动的当前状态。反斜杠(\)表示我们正在使用键路径,这意味着我们所指的是属性本身而不是其值。每当属性值更改时,就会调用onChange修饰符,在这里我们可以获取生命周期状态!
就这么简单。
推荐
基础文章推荐
经典教程推荐
技术源码推荐
推荐文章
CoreData篇
Combine篇
TextField篇
- 《SwiftUI 一篇文章全面掌握TextField文本框 (教程和全部源码)》
- 《SwiftUI实战之TextField风格自定义与formatters》
- 《SwiftUI实战之TextField如何给键盘增加个返回按钮(隐藏键盘)》
- 《SwiftUI 当键盘出现时避免TextField被遮挡自动向上移动》
- 《SwiftUI实战之TextField如何给键盘增加个返回按钮(隐藏键盘)》
JSON文件篇
一篇文章系列
- SwiftUI一篇文章全面掌握List(教程和源码)
- 《SwiftUI 一篇文章全面掌握TextField文本框 (教程和全部源码)》
- SwiftUI一篇文章全面掌握Picker,解决数据选择(教程和源码)
- SwiftUI一篇文章全面掌握Form(教程和源码)
- SwiftUI Color 颜色一篇文章全解决
技术交流
QQ:3365059189
SwiftUI技术交流QQ群:518696470
- 请关注我的专栏icloudend, SwiftUI教程与源码
https://www.jianshu.com/c/7b3e3b671970