本文主要认识SwiftUI,并且学会如何使用SwiftUI。
主要内容:
- 什么是SwiftUI
- 创建的第一个SwiftUI工程
- SwiftUI的简单使用
1. 什么是SwiftUI
2019年WWDC大会上,苹果在压轴环节向大众宣布了基于Swift语言构建的全新UI框架——SwiftUI,开发者可通过它快速为所有的Apple平台创建美观、动态的应用程序。
SwiftUI的运行速度优于UIKit,他减少了界面的层次结构,因此可以减少绘制步骤,并且他完全绕过了CoreAnimation,直接进入Metal,可以有优秀的渲染性能。
1.1 认识
SwiftUI is a user interface toolkit that lets us design apps in a declarative way.
SwiftUI 就是⼀种声明式的构建界面的用户接口工具包。
SwiftUI使用声明式的语法构建UI,我们只需要向系统声明UI的View样式,以及View如何转换状态,其他的过程都交给系统去处理。
声明式语法和指令式语法的区别:
- 声明式的我们需要提前声明好每个view的各种状态,以及状态转变的条件。后续界面和用户在互动时,系统会帮我们自动进行状态切换。
- 指令式的我们需要给每个view先设置好默认状态,后续界面和用户在互动时,需要通过指令不停的去转变view的状态
- 因此声明式的UI是提前声明好各种状态,系统会自动帮我们进行状态切换。指令式的UI是通过我们设定的指令来转换状态
- 比如界面调整、用户交互、机型适配,UIKit都需要手动调整view,对于SwiftUI我们只需要声明好我们想要的样式,系统会帮我们去调整view。
- 可以这么说,SwiftUI相比于UIKit更加的抽象化了
1.2 优点
- 统一苹果终端
- 在 SwiftUI 出现之前,苹果不同的设备之前的开发框架并不互通,增加开发者所需消耗的时间精力,也不利于构建跨平台的软件体验
- SwiftUI具有了跨平台性,苹果的平台都可以使用,iOS、macOS、tvOS、watchOS
- 降低界面开发难度
- UIKit 的基本思想要求ViewController 承担绝⼤部分职责,它需要协调 model,view 以及⽤⼾交互。这带来了巨⼤的sideeffect 以及⼤量的状态
- SwiftUI是声明式的构建方式,我们只需要声明好界面系统会自动转换状态,搭建界面更加的简单
- 更加高效
- 默认使用Metal渲染,性能非常高,比UIKit要好
- 更扁平化的内联数据结构去分配内存,值类型。占用内存很少(所以在轻应用的开发更适合使用SwiftUI)
- 代码量相比UIKit要更少,效率更高
- 更好的配合Swift语言
- SwiftUI 使用了大量 Swift 的语言特性
1.3 特点
- 声明式语法
- 与UIKit布局相比,更加的抽象化,只需要向系统声明界面样式以及样式变化条件,其他的系统会帮我们实现,不需要我们自己去调整视图
- 链式调用属性
- 链式调用是 Swift 语言的一种特性,就是使用函数式编程,可以像链条那样不断地调用函数,中间不需要断开。使用这种方式可以大大减少代码量。
- 除了系统提供的属性可以使用之外,开发者也可以进行自定义
- 例如将不同字体、字号、行间距、颜色等属性统合起来,可以组合成为一个叫「标题」的文字属性。之后凡是需要将某一行文字设置成标题,直接添加这个自定义的属性即可,使用这种方式进行开发无疑能够极大的避免无意义的重复工作,更快的搭建应用界面框架。
- 界面元素的组件化
- UIKit耦合了很多的操作逻辑,很难进行移植,更遑论组件化了
- 而SwiftUI仅仅声明界面样式,所以是可以将复杂视图的拆分出来组件化
- 甚至还可以在其他平台使用,以此跨平台
- 一般我个人会将视图组件区分为基础组件、布局组件和功能组件
- 与UIKit互相兼容
- 把 UIKit 中已有的部分进行封装,提供给 SwiftUI 使用。开发者需要做的仅仅是遵循UIViewRepresentable协议即可
- 并且在已有的项目中,也可以仅用 SwiftUI 制作一部分的 UI 界面
- 两种代码的风格是截然不同的,但在使用上却基本没有性能的损失。在最终的运行效果上,用户也无法分辨出两种界面框架的不同。
-
真实数据源(Source of truth)(重点)
- SwiftUI中的数据源一定会是真实的,也就是准确的
- 在OC中,一个view的状态由多种因素导致的,不同的来源,不同的逻辑操作(因此需要考虑及时更新界面)
- 因此在Swift中,提供了单一数据源的说法
- 只要在属性声明时加上 @State 等关键词,就可以将该属性和界面元素联系起来,在每次数据改动后,都有机会决定是否更新视图。
- 系统将所有的属性都集中到一起进行管理和计算,也不再需要手写刷新的逻辑。
- 因为在 SwiftUI 中,页面渲染前会将开发者描述的界面状态储存为结构体,更新界面就是将之前状态的结构体销毁,然后生成新的状态。
- 而在绘制界面的过程中,会自动比较视图中各个属性是否有变化,如果发生变化,便会更新对应的视图,避免全局绘制和资源浪费。
- 使用这种方式,读和写都集中在一处,开发者就能够更好地设计数据结构,比较方便的增减类型和排查问题。而不用再考虑线程、原子状态、寻找最新数据等各种细节,再决定通知相关的界面进行刷新。
- 设计工具和快速预览功能
- Xcode 包含直观的设计工具,只需拖放操作就能使用 SwiftUI 轻松构建界面。
- 拖放操作
- 动态替换
- 预览
1.4 SwiftUI和UIKit的区别
- SwiftUI是描述式的(声明式的),UIKit是指令式的
- UIKit的View都是一个Class,SwiftUI的View是Struct
- Swift的View不需要像UIKit那样操作逻辑控制,只负责展示
- 因为结构体比类更简单更轻量,创建几乎没有开销
- Swift的运行速度要优于UIKit
- Swift的开发难度要低于UIKit
2. 创建的第一个SwiftUI工程
2.1 创建SwiftUI工程
创建过程和之前一样,只不过这里要选择Swift语言和SwiftUI
查看界面如下:
2.2 SwiftUIAPP代码解析
代码:
import SwiftUI
@main
struct TodoSwiftUIApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
说明:
- 这个结构体就是一个APP,继承自APP
- 定义了一个body属性,拿到APP的窗口
- 这里调用ContentView就是我们定义的View
- 所以这里就是拿到我们创建的APP的UI
2.3 ContentView结构体解析
代码:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, world!") .padding()
}
}
说明:
- 结构体ContentView定义了屏幕的UI,遵守View协议
- 所有在SwiftUI中显示的元素都需要遵守View协议
- 因此,必须声明一个叫做body的属性,这个body可以返回整理好的View,详情可以看博客Swift基础语法(十一)泛型
- some是不透明类型,不透明在于不知道返回的具体类型是什么,只知道遵守View协议
- 当前body内只包含了一个Text视图,文本视图是图形化的,显示一行或多行只读文本的视图,也就是说他是一个文本标签(先简单的看做是OC中的Label,后续文章会详细介绍SwiftUI中的View)
2.4 预览认识
代码:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
说明:
- UI的预览结构体,遵守PreviewProvider协议
- 定义了一个previews变量。它拿到的也是ContentView(),即UI
- 它可以修改我们的预览属性
比如我们想要在iPhone SE上进行预览,需要进行如下操作:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(). previewDevice("iPhone SE (2nd generation)")
}
}
通过这种方式就可以查看不同机型下的预览
预览画面查看
说明:
- 可以在这里选择打开或关闭预览界面
- 在预览设置中,共有六项
- Preview是刷新视图
- 运行预览
- 发快递
- 切换横竖屏
- 设置预览配置
- 新增预览界面
- 预览配置
- 调节预览尺寸
3. SwiftUI的简单使用
代码:
struct ContentView: View {
var body: some View {
VStack(alignment: .center, spacing: 20){
Text("Hello")
.foregroundColor(.red)
Button(action:{
print("button tapped")
}){
Text("Press Me")
}
.foregroundColor(.green)
}
}
}
说明:
- 所有视图代码都放在body中
- VStack是进行垂直布局,alignment表示对齐方式,这里是居中对齐,还有spacing表示内间距,为20
- Text是文本视图
- Button是按钮,action是点击后的操作,Text("Press Me")是按钮文本
- foregroundColor是Modeifiers,后续会详细讲解
结果: