2.1 SwiftUI 的基础项目模版

首先我们先在 Xcode 创建一个 SwiftUI 项目,步骤如下:

步骤一:打开 Xcode(必须11及以上版本) 并点击 Create a new Xcode project,或者在菜单栏选择 File > New > Project

Create a new Xcode project

步骤二:在模版选择器选择 Single View App,然后点击下一步。

Single View App

步骤三:给项目命名,然后勾选 Use SwiftUI 选项,最后找个路径保存项目。

Use SwiftUI

至此一个项目就算有基础模版了,也可以看到对应的文件结构。

SwiftUI

下面简单介绍下各个文件的作用:

SwiftUI 项目的基础结构差不多就这样,文件不多,代码也少。我们要把重点放在 ContentView.swift 上面,因为这是应用程序的主要内容,也是我们接下去要开始尝试各种 SwiftUI 代码的地方。

首先,为什么 ContentView.swift 的内容可以显示在屏幕上?

看上面的文件列表里 SceneDelegate.swift 的描述,我们打开该文件,可以看到如下代码:

let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()

这段代码定义里一个叫做 ContentView 的实例,并且把它放置在 window 里,以便可以在屏幕上显示。也可以理解成应用程序加载完成后就进入了 ContentView

打开 ContentView.swift 文件,可以看到如下代码:

import SwiftUI

struct ContentView : View {
    var body: some View {
        Text("Hello World")
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

代码不多,首先注意 ContentView 是一个结构体(struct),如果是熟悉 UIKit 的开发者对 struct 并不陌生,我们可以为结构体定义属性(常量、变量)和添加方法,从而扩展结构体的功能。

再者, ContentView 符合 View 的协议(protocol),在 SwiftUI 展示的所有内容都需遵循 View 协议。这实际上只意味着一件事:你需要一个名为 body 的属性来返回某种View。

这个 body 返回的是 some Viewsome 这个关键字是 Swift 5.1 的新特性Opaque Result Types。默认场景下 View 协议是没有具体类型信息的,只有类型约束,但是用 some 修饰后,编译器会让 protocol 的实例类型对外透明,。在上述代码中,some 的意思是:它会返回某种 View(Text, Image…),符合 View 的协议内容,但是 SwiftUI 不需要知道具体返回的是什么,当然不能返回空,也不能随机返回(上述的代码是有写清楚返回类型)。

最后,在 ContentView 下面有一个类似但又不同的结构体 ContentView_Previews,它并不符合 View 协议,因为它是专门用来在 Xcode 里显示预览视图用的,而不会出现在真实的应用屏幕上。这个结构体被 #if DEBUG#endif 包围着,意思是这里面的代码只会在调试环境中运行,在成品生产环境中无实际意义。