SwiftUI的declarative programming,再加上Combine的State和Data Flow Control,让我们可以用Reactive Programming来写iOS app。今天要写一个简单的小app来向你们证明这有多简单,比之前UIKit和OC写起来简单多了,谁用谁知道!
之前在简书上看到一面试题:用UILabel写一个循环播放的通告,就写一下这个吧。但我想多展示一些学到的知识,所以在写之前,我们要选择一个design pattern。有了SwiftUI,以前的UIViewController的需求就更少了,所以我们选择MVVM(Model-View-ViewModel)。熟悉React的开发者可能会想能不能用Redux,答案是肯定的!我下一步就会写一个更复杂的拥有完整功能的app,就用SwiftUI、Combine和Redux来实现,到时候会放到github上去。
Github Source
先来简单说一下这个app的“知识点”:
1、Timer
因为通告是循环播放的,我们需要一个timer让通告每秒更新一次,这个不需要在background进行,所以我们就用Runloop.main中的timer就行。Combine有个方便的方法创建一个timer publisher:
Timer
.publish(every: interval, on: .main, in: .common)
// timer publisher只有call connect()之后才会开始发送,autoconnect就是只要用subscriber就自动开始
.autoconnect()
2、State & Data Flow
-
@State
如果一个variable只在View内部使用,那么我们可以用@State来声明,声明之后无论何时这个variable更新,那么View也会随之更新,栗子:
@State private var isOn = false
var body: some View {
VStack{
Button(action: {
self.isOn.toggle()
}) {
Text("点我")
}
if isOn {
Text("开了")
}
}
}
-
@Binding
如果这个View中有child view,在child view中,我们也想使用isOn这个state variable,这时候我们就需要在child view中声明一个binding variable
var body: some View {
VStack{
Button(action: {
self.isOn.toggle()
}) {
Text("点我")
}
if isOn {
Text("开了")
}
CView(isOn: $isOn) // a
}
}
struct CView: View {
@Binding var isOn: Bool
var body: some View {
VStack{
Text("Child View")
if isOn {
Text("我也开了")
}
}
}
}
a) 注意在给CView传入isOn的时候前面要加$, 因为CView中的isOn前面有@Binding,他是一个Binding<Bool>, 在body里的isOn加上$也就成了Binding<Bool>
b) 这不是完整的代码,每次点击Button时,因为isOn的更新,child view和parent view会一起刷新
-
@ObservableObject
ObservableObject是一个protocol,conform to ObservableObject的class中可以用@Published来wrap属性,一旦用了@Published,每当这个属性更新时,使用这个class和这个属性的View就会刷新一下, ViewModel就是最适合conform的
class AnnouncementViewModel: ObservableObject {
@Published private(set) var announcement : Announcement
// 其他完整代码可以到github下载
}
-
@ObservedObject
有了ObservableObject之后,我们就可以在View里声明@ObservedObject了。声明之后就可以在UI中显示这个object的一些属性,然后每当这个属性更新,UI也会随之变化
struct TestView: View {
@ObservedObject var viewModel = AnnouncementViewModel()
var body: some View {
Text(viewModel.announcement.title)
}
}
网友评论