대부분 iOS ViewModel에서 상태를 관리하기 내부에 쓰이는 값들을 하나의 구조체로 그 객체가 갖는 상태를 선언해서 관리한다.
@Observable class ViewModel{
var state:State
struct State{
var isFirstAppear = true
var isTipAlertPresented = false
}
...
}
자세한 Observable 동작은 공식문서에...
Migrating from the Observable Object protocol to the Observable macro | Apple Developer Documentation
Update your existing app to leverage the benefits of Observation in Swift.
developer.apple.com
실험 가설
- 2개의 State 내부 변수를 둔다.
- 두 변수 각각
withObservationTracking
검사하는 메서드를 만든다. - 한 변수만 변화하고 두 메서드 모두 실행한다.
- 두 메서드의
withObservationTracking
모두 onChange 핸들러에 print 문이 출력되면 Observable의 고유한 프로퍼티 접근에 위배된다.
ViewModel 코드
@Observable
public final class ViewModel {
public var state: State
public init() {
self.state = State()
}
@MainActor
public struct State: Equatable {
public var isFirstAppear = true
public var isTipAlertPresented = false
}
public func renderIsFirstAppear() {
withObservationTracking {
print("renderIsFirstAppear: ",self.state.isFirstAppear)
} onChange: {
print("Schedule renderer. renderIsFirstAppear")
}
}
public func renderIsTipAlertPresented() {
withObservationTracking {
print("renderIsTipAlertPresented: ",self.state.isTipAlertPresented)
} onChange: {
print("Schedule renderer. renderIsTipAlertPresented")
}
}
}
Timer 실행 코드
Task {
let exploreVM = ViewModel()
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
exploreVM.state.isFirstAppear.toggle()
exploreVM.renderIsFirstAppear()
exploreVM.renderIsTipAlertPresented()
}
exploreVM.renderIsFirstAppear()
exploreVM.renderIsTipAlertPresented()
}
실행 결과
두 render 함수 모두 호출된다..!
해결법 - State에 Observable을 걸어준다면?
State에 Observable을 주고 class로 바꿈
import Observation
@Observable
public final class ExploreViewModelObservable {
...
@Observable
public class State {
public var isFirstAppear = true
public var isTipAlertPresented = false
}
}
실행 결과
값을 바꾼 renderIsFirstAppear의 render만 호출된다
If) State에 Observable을 안 걸어주고 class로만 한다면?
@Observable
public final class ExploreViewModelObservable {
...
public class State {
public var isFirstAppear = true
public var isTipAlertPresented = false
}
}
실행 결과
두 랜더링 모두 호출이 안된다..! Observer가 없다는 뜻..!
ps. 사실 웬만하면 크게 렌더링 성능이 떨어질까 싶긴한데...
테스트 파일
'이모저모 > Swift' 카테고리의 다른 글
WWDC - Async algorithm 패키지 (0) | 2024.10.20 |
---|---|
Swift - Task.Sleep vs Timer (0) | 2024.04.30 |
ios - 이미지 중복 사용 방지 처리 (0) | 2024.01.25 |
TaskCounter로 병렬 작업 완료 계수 파악하기 (0) | 2023.12.13 |
UserDefaults with propertyWrapper (0) | 2023.11.30 |
댓글