SwiftUI에서는 데이터를 다루는데 여러 프로퍼티들이 사용된다.
struct Chapter5ContentView: View {
@State private var isFavorite: Bool = true
@State private var count : Int = 0
var body: some View {
VStack(spacing: 30) {
Toggle(isOn: $isFavorite) {
Text("isFavorite : \(isFavorite.description)")
}
Stepper("Count : \(count)", value: $count)
}
.padding()
}
}
위 예제를 한번 보자.
상태 프로퍼티를 정의한다는 것은 '데이터가 변경되면 뷰 역시 변경되어야 한다.' 라는 뜻이므로 변경 사항이 감지될 때마다 뷰를 재생성 해줘야한다.
class User2: ObservableObject {
let name : String = "User Name"
var score: Int = 0
}
struct Chapter5ContentView: View {
@State private var isFavorite: Bool = true
@State private var count : Int = 0
@ObservedObject var user : User2
var body: some View {
VStack(spacing: 30) {
Text(user.name)
Button(action: { self.user.score += 1 }) {
Text(user.score.description)
}
}
.padding()
}
}
struct Chapter5ContentView_Previews: PreviewProvider {
static var previews: some View {
Chapter5ContentView(user: User2())
}
}
위 예제를 보면 ContentView가 User2 모델에 의존성을 지니고 있고 모델의 값을 사용하고 있어서 정상 동작 할 것 같지만 그렇지 않다. 어떠한 값이 변경되었을 때 뷰를 갱신해야하는지 알려주지 않았기 때문이다. 이러한 기능을 하는 프로퍼티가 바로 @Published 이다.
class User2: ObservableObject {
let name : String = "User Name"
@Published var score: Int = 0
}
위 예제처럼 score 변수에 @Published 프로퍼티를 선언해놓으면, User2 모델을 참조하고 score 변수를 사용하고 있는 뷰에서 값의 변경을 감지하여 뷰를 업데이트 한다.
objectWillChange는 @Published처럼 프로퍼티의 변경 시점에 즉시 알리는 것이 아니라, ObservableObject 프로토콜에 선언된 프로퍼티를 통해 원하는 시점에 사용할 수 있다.
let objectWillChange = ObjectWillChangePublisher()
var score = 0 {
willSet { objectWillChange.send() }
}
위 예제를 보면 @Published는 ObjectWillChangePublisher가 send 메서드를 호출하는 로직을 간소화 한 것이다. 그러므로 둘의 기능은 동일하고, 객체에 알림을 전달하는 시점을 결정할 수 있는지에 대한 차이가 있다.
@EnvironmentObject는 모델에 간접적인 의존성을 가지는 레퍼 타입이다. 반면 @ObservedObject는 직접적인 의존성을 가지는 둘의 차이점이 있다.
struct ContentView: View {
var body: some View {
SuperView(user: User2())
}
}
struct SuperView: View {
@ObservedObject var user: User2
var body: some View { SubView(user: user) }
}
struct SubView: View {
@ObservedObject var user: User2
var body: some View { Text(user.name.description) }
}
struct ContentView: View {
var body: some View {
SuperView().environmentObject(User2())
}
}
struct SuperView: View {
var body: some View { SubView() }
}
struct SubView: View {
@EnvironmentObject var user: User2
var body: some View { Text(user.name.description) }
}
잘 정리된 글 감사합니다.