-
Notifications
You must be signed in to change notification settings - Fork 3
[이준복] Data Essentials in SwiftUI ‐ @StateObject, @ObservableObject, @EnvironmentObject
junbok97 edited this page Jul 30, 2024
·
2 revisions
https://junbok97.tistory.com/366
- SwiftUI는 View와 View의 State관리가 중요
- SwiftUI는
@State를 통해 Single Source of Truth(SOT) 를 나타낼수 있음 - SwiftUI는
@State로 선언된 상태 프로퍼티의 저장소를 관리 -
@Binding을 통해 Single Source of Truth(SOT) 에 접근 가능 -
@Binding을 할때는 @State 로 선언된 상태 프로퍼티의 이름에 prefix로 $표시를 추가해 사용 - SwiftUI는 State프로퍼티가 변하면 State프로퍼티 가 포함된 View 계층구조의 일부 View들을 업데이트
- Single Source of Truth(SOT) 에 의한 상태(State) 관리
- UIKit에서는 데이터가 여기저기서 주고 받아지고, 그렇게 받아진 데이터를 여기저기서 수정. 결국에는 어떤게 진짜인지 헷갈리고 복사된 데이터 값들이 다 다르다 보니 버그에 취약해지기 때문에 개발자가 신경써야할 게 많았음. SwiftUI에선 그런 고민들을 시스템에서 다 처리해주자 !
- 지난 글을 통해 배운
@State,@Binding이 두가지의 프로퍼티 래퍼는Value Type을 위한 것 -
struct,enum,Int,Bool등
-
@StateObject,@ObservedObject,@EnvironmentObject -
@EnvironmentObject는 후반부에서 계속 - Single Source Of Truth
- Value :
@State - Reference :
@StateObject
- Value :
- Reference of SOT
- Value :
@Binding - Reference :
@ObservedObject
- Value :
1
2
3
- 프로퍼티 래퍼
@StateObject,@ObservedObject를 사용하려면 class에선protocol ObservableObject을 채택해주어야 함 -
protocol ObservableObject은AnyObject를 채택 중 즉 class Type만 사용가능하다 - class에
ObservableObject을 채택하고 class 내에서 관찰할 프로퍼티에@Published를 사용
-
@Published프로퍼티에서 변화가 생기면 값을 방출하여 SwiftUI가 뷰를 다시 그림- 값을 어디로 방출?
-
protocol ObservableObject의objectWillCahnge로
class ReadingListStore: ObservableObject { @Published var listName: String = "Book List" }
-
ObservableObjectclass 를 관찰하려는 View에서@observedobject를 붙혀 사용 -
@observedobject는 뷰 내부에서 직접 초기화가 가능 - 하지만
@observedobject는 인스턴스를 소유하고 있지 않고 있기 때문에 문제가 발생
- ReadingListViewer의 body가 호출될때마다 ReadingList() 로 인해 ReadingList.store의 Repeated heap allocation 문제 발생
- 이때 사용하는것이
@StateObject - StateObject lets SwiftUI instantiate your ObservableObjects at the right time, so you don't incur unnecessary heap allocations, and you don't lose data.
struct ReadingList: View { @StateObject private var store = ReadingListStore() var body: some View { ReadingItem(store: store) } } struct ReadingItem: View { @ObservedObject var store: ReadingListStore var body: some View { } }
9
10
11
12
Note that the lifetime of a view is separate from the lifetime of a struct that defines it.
-
ObservableObject가 필요한 곳이 멀리 떨어져 있다면 ?
-
ObservableObject가 필요하지 않은 뷰임에도 하위 뷰로 전달하기 위해서 추가해주어야 함
class MyObservableObject: ObservableObject { } struct View1: View { @StateObject var myObservableObject = MyObservableObject() var body: some View { View2(myObservableObject: myObservableObject) } } struct View2: View { @ObservedObject var myObservableObject: MyObservableObject var body: some View { View3(myObservableObject: myObservableObject) } } struct View3: View { @ObservedObject var myObservableObject: MyObservableObject var body: some View { View4(myObservableObject: myObservableObject) } } // myObservableObject 필요한 곳 struct View4: View { @ObservedObject var myObservableObject: MyObservableObject var body: some View { myObservableObject } }
- 이럴때 사용하는 것이
@EnvironmentObject
- 뷰에
environmentObject로 등록하면 계층구조에 상관없이 접근 가능 -
@EnvironmentObject를 사용하여ObservableObject가 필요한 뷰에서 접근
class MyObservableObject: ObservableObject {} struct MyContentView: View { var body: some View { View1() .environmentObject(MyObservableObject()) } } struct View1: View { var body: some View { View2() } } struct View2: View { var body: some View { View3() } } struct View3: View { var body: some View { View4() } } struct View4: View { @EnvironmentObject var myObservableObject: MyObservableObject var body: some View { myObservableObject } }
Luckily, we have a solution for this problem with EnvironmentObject. EnvironmentObject is both a view modifier and a property wrapper.
https://developer.apple.com/videos/play/wwdc2020/10040/
https://developer.apple.com/documentation/Combine/ObservableObject
https://developer.apple.com/documentation/combine/published
https://developer.apple.com/documentation/swiftui/observedobject
https://developer.apple.com/documentation/swiftui/stateobject
https://developer.apple.com/documentation/Combine/ObservableObject
https://developer.apple.com/documentation/swiftui/environmentobject