学习路径:
SwiftUI 官方文档
SwiftUI 源码教程
GitHub Package 论坛
SwiftUI
的特点
- 声明式 UI (类比 React JSX,Flutter)
- 响应式数据 (类比 mobx,vue)
- “CSS In JS”
- 链式调用(官方术语叫 ViewModifier,类似 react 里面的 HOC 概念)
声明式的界面开发
近年来,随着编程技术和思想的进步,使用声明式或者函数式的方式来进行界面开发,已经越来越被接受并逐渐成为主流。最早的思想大概是来源于 Elm
,之后这套方式被 React
和Flutter
采用,这一点上SwiftUI
也几乎与它们一致。总结起来,这些UI
框架都遵循以下步骤和原则:
1、使用各自的DSL
来描述[UI
应该是什么样子],而不是用一句句的代码来指导[要怎样构建UI
]。
比如传统的 UIKit
,我们会使用这样的代码来添加一个“Hello World”
的标签,它负责“创建label
”,“设置文字”,“将其添加到View
上”:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 80, 40)];
label.backgroundColor = [UIColor grayColor];
label.text = text;
label.textColor = [UIColor orangeColor];
label.font = [UIFont systemFontOfSize:20];
label.textAlignment = NSTextAlignmentLeft;
[self.view addSubview:label];
相对于SwiftUI
,我们只需要告诉SDK
我们需要一个文字标签:
struct BadgeSymbol: View {
var body: some View {
Text("Hello, World!")
}
}
2、然后框架内部读取这些View
的声明,负责将它们以合适的方式绘制渲染。
注意,这些 View
的声明只是纯数据结构的描述,而不是实际显示出来的视图,因此这些结构的创建和差分对比并不会带来太多性能损耗。相对来说,将描述性的语言进行渲染绘制的部分是最慢的,这部分工作将交由框架以黑盒的方式为我们完成。
3、如果 View
需要根据某个状态 @state
进行改变,那我们将这个状态存储在变量中,并在声明 View
时使用它:
struct BadgeSymbol: View {
@State var name: String = "Lynn"
var body: some View {
Text("Hi \(name)")
}
}
4、状态发生改变时,框架重新调用声明部分的代码,计算出新的 View
声明,并和原来的View
进行差分,之后框架负责对变更的部分进行高效的重新绘制。
SwfitUI
数据流转流程
- 该行为触发数据改变,并通过
@State
数据源进行包装; -
@State
检测到数据变化,触发视图重绘; -
SwiftUI
内部按上述所说的逻辑,判断对应视图是否需要更新UI
,最终再次呈现给用户,等待交互。
每个节点的数据流转都是单向的、独立的。
使用描述方式开发,大幅减少了在 app 开发者层面上出现问题的机率。
@State
- 视图和数据存在依赖,数据变化要同步到视图;
@Binding
- 父子视图直接有数据的依赖,数据变化要同步到父子视图;
@BindableObject
- 外部数据结构与SwiftUI
建立数据存在依赖;
@EnvironmentObject
- 跨组件快速访问全局数据源;
网友评论