1. 简介
如图,自 Xcode 11 之后,基本的 单一视图应用程序(Single View App)模板 为我们提供以下内容:
AppDelegate.swift
- 它负责监视外部事件。
- 例如: 如果另一个应用程序试图向我们发送要一个要打开的文件。
SceneDelegate.swift
- 它负责管理应用程序的显示方式。
- 例如: 让多个实例同时运行,或者当一个实例移动到后台时采取操作/措施。
ContentView.swift
- 它是我们最初的用户界面。
- 如果这是一个 UIKit 项目,它就相当于 Xcode 提供给我们的 ViewController 类。
Assets.xcassets
- 它是项目的资产目录。
- 存储着我们项目中使用的所有图像和颜色。
LaunchScreen.storyboard
- 它是在我们的应用加载时显示的屏幕。
Info.plist
- 它是一个属性列表文件,用于存储应用程序的系统级设置。
- 例如: 应该在 iOS 主屏幕上的图标下面显示什么名称。
Preview content
- 它是一个名为 Preview content 的组,其中包含另一个名为 Preview Assests 的资产目录。
就是这样 - 只有少量的代码和资源,这意味着我们可以在此基础上进行构建。
2. 查看 SceneDelegate
事实上,我们真正关心的、也是唯一重要的部分是 ContentView.swift
。这是我们应用程序的主要功能,在这里我们可以立即开始尝试各种 SwiftUI
代码。
不过,我们首先要弄清楚的是: 是什么让 ContentView.swift 显示在屏幕上?
上面我们提到: SceneDelegate.swift
负责管理应用程序的显示方式。那么,我们打开 SceneDelegate.swift
,就会看到下面的代码:
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
这段代码创建了一个新的 ContentView
实例(这是我们即将看到的主要功能),并将其放置在窗口中,以便在屏幕上显示。通过显示 ContentView
的第一个实例,可以有效地引导我们的应用程序,并从那里结束 - 那么接下来你想做什么?
3. 查看 ContentView
打开 ContentView.swift
,让我们看看一些实际的 SwiftUI 代码。我们应该可以看到这样的代码:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
这不是很多代码,但它实际上包含了大量代码。
首先,请注意,
ContentView
是一个结构体。熟悉 UIKit 的开发人员都知道 - 我们从用户界面的所有值类型的不变性和简单性中获益巨大!其次,
ContentView
遵守View
协议。我们想在 SwiftUI 中显示的所有内容都需要遵守View
协议,这实际上只意味着一件事: 我们需要一个名为body
的属性来返回some View
。第三,
body
的返回类型是some View
。some
关键字是在 Swift 5.1 中新引入的,是一个名为 不透明返回类型(opaque return types) 功能的一部分,在这种情况下,它的意思是 将返回某种视图,但 SwiftUI 不需要知道(或关心)什么。
重要说明: 返回
some View
意味着body
属性将返回遵守View
协议的内容。我们不能返回很多东西或忘记返回任何东西,否则,Swift 编译器将拒绝构建我们的代码。为了清楚起见,我们的视图 body 必须始终返回一个子视图。
第四,body 属性中有
Text("hello world")
,它创建了文本内容为 “hello world” 的标签。最后,在 ContentView 下面的是一个类似但不同的 struct,称为
ContentView_Previews
。它不遵守View
协议,因为它专门用于在 Xcode 中显示 视图预览(Preview),而不是在真正的应用程序中显示在屏幕上。这就是为什么你会看到它在#if DEBUG
和#endif
之间 - 当我们的应用程序在调试环境中运行时,这段代码只构建在 成品(finished product)中,因为它在生产应用程序(Production app)中没有意义。