일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- @Environment
- URL(string:)
- @State
- RxCocoa
- operator
- SWIFT
- graphql
- @Binding
- init
- Operater
- SwiftUI
- init?
- NavigationLink
- subject
- IOS
- nonisolated
- ios14
- @EnvironmentObject
- RxSwift
- Bug
- RFC1738/1808
- NullObject
- Creating Operators
- nestjs
- vim
- Operators
- swift6
- typeorm
- dismiss
- Xcode
- Today
- Total
Tunko Development Diary
SwiftUI - @StateObject, @ObservedObject 이해하기 본문
SwiftUI에서 사용하는 @StateObject 및 @ObservedObject는 View의 변경사항을 감지하여 View를 업데이트 하도록 지시합니다.
두가지는 비슷한 효과를 내지만 중요한 차이점이 있습니다.
여러 글들을 참고하고 실제로 시도해본결과 이렇게 요약할 수 있었습니다.
@StateObject를 사용한 View는 부모뷰 변경에도 변경이 없습니다.
@ObservedObject를 사용한 View는 부모뷰의 변경이 일어나면 초기화 됩니다.
즉, 속성 래퍼가 값을 기억하고 있지않습니다.
단지 관찰할 뿐이죠.
말로만 하면 재미 없으니 그림으로 보겠습니다.
아래 그림을 보면 3개의 값이 있고 각각 @State, @StateObject, @ObservedObject로 선언된 value: Int 를 나타냅니다.
View의 구조
- ContentView (최상위 흰색 배경)
- RootView (주황색 배경)
- SubView (검정, 빨강, 파랑 버튼3개)
- RootView (주황색 배경)
그리고 1개의ViewModel을 사용합니다.
class ViewModel: ObservableObject {
@Published var value: Int = 0
func increment() {
value += 1
}
}
단순하게 value 값을 1개 늘려주는 ObservableObject 객체입니다.
ObservableObject 로 선언된 객체는 @ObservedObject
, @StateObjcet
속성 래퍼로 결합하여 SwiftUI에 View와 연결되며 관찰된 객체의 변경이 생길때마다 View를 다시 그려줍니다.
따라서 위 영상처럼 값이 버튼을 눌러 increment() 를 호출하여 값을 올리면 화면이 그순간 다시 그려지면서 갱신됩니다.
여기서 중대한 차이점이 있습니다.
보시면 아시겠지만 @StateObject는 주황 배경 버튼을 눌러도 그대로 유지되지만, 반면 @ObservedObject 의 값을 가진 버튼은 0으로 초기화 됩니다.
한줄요약
부모뷰의 Reload가 일어날때 ObservedObject 객체 사용중인 View는 초기화 되고 StateObject 객체를 사용중인 View는 상태를 유지한다.
이대로도 이해하기 쉽지만 좀더 직관적인 예시를 들어보겠습니다.
아래 영상은 스크롤뷰의 Offset 값을 @State
로 가져와서 스크롤시 화면의 값이 변경됩니다.
극단적인 예시 일 수 있겠지만 부모뷰의 값이 매 순간 변화할때는 위 영상처럼 @ObservedObject
객체를 사용한 뷰의 경우 매번 초기화를 합니다.
'Development > SwiftUI' 카테고리의 다른 글
SwiftUI) Null(nil) Object Pattern 활용하기 (0) | 2023.09.10 |
---|---|
SwiftUI) .sheet 배경 투명하게 만들기 (ios16.4 대응) (0) | 2023.04.05 |
xcode 14.2 - Info.plist contained no UIScene configuration dictionary (looking for configuration named "(no name)") 해결방법 (0) | 2023.01.20 |
SwiftUI) 알아두면 편한 FixedSize! (0) | 2022.10.12 |
SwiftUI) @Environment와 dismiss를 사용하는 올바른 방법 (0) | 2022.10.03 |