SwiftUI全攻略——2.数据流和修饰符
1. @Binding and @State
@Binding
SwiftUI中的View都是结构体,在Swift中,结构体都是值传递,使用@Binding
修饰的属性会变成引用传递,一般用于连接两边的View,传递数据。
@State
也是用来修饰属性,当@State
修饰的属性值改变的时候,View层也会自动变化,我们称之为响应式编程,数据视图双向绑定。
struct PlayerView: View {
var episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
.font(.title)
if isPlaying {
Text(episode.description)
.font(.body)
}
PlayButton(isPlaying: $isPlaying)
}
.padding()
}
}
struct PlayerView_Previews: PreviewProvider {
static var previews: some View {
PlayerView(episode: Episode.data())
}
}
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
}
}
}
struct PlayButton_Previews: PreviewProvider {
@State static private var isPlaying = false
static var previews: some View {
PlayButton(isPlaying: $isPlaying)
}
}
PlayerView
把isPlaying
用@State
修饰,之后传递给子View PlayButton
,在PlayButton
中使用@Binding
修饰的isPlaying
接收到了传递过来的数据,在内部修改,可以直接更新父View。
自此就实现了数据和View的双向绑定,更多细节可以参考Combine框架,MVVM设计思想,RxSwfit设计思想。
2. @State or @ObservedObject ?
首先使用场景不同,
@State
一般声明为private
,只用于当前View。
@ObservedObject
适用于由外部向View内传递数据,在MVVM架构中ViewModel要用@ObservedObject
修饰
其次修饰的数据类型不同,
@State
无法修饰Class
类型的数据,一般就修饰Struct
Bool
String
。
@ObservedObject
必须修饰Class
类型的数据,Class
也要遵守ObservableObject
协议。内部需要观察的属性也需要添加@Published
修饰符,这样被标记的属性更新,才会通知到View
struct PlayerView: View {
var episode: Episode
@ObservedObject var user: User
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
.font(.title)
if isPlaying {
Text(episode.description)
.font(.body)
}
PlayButton(isPlaying: $isPlaying, user: user)
}
.padding()
}
}
struct PlayerView_Previews: PreviewProvider {
static var previews: some View {
PlayerView(episode: Episode.data(), user: User(name: "", age: 0, score: 0))
}
}
import Combine
final class User: ObservableObject {
var name: String = ""
var age: Int = 0
@Published var score: Int = 0
init(name: String, age: Int, score: Int) {
self.name = name
self.age = age
self.score = score
}
init() {
}
}
github仓库地址 https://github.com/SunZhiC/LearningSwiftUI
References
Introducing SwiftUI: Building Your First App
@State vs @ObservableObject - which and when?