SwiftUI

Making classes observable

ziziDev 2024. 8. 2. 13:26
반응형

Making classes observable

@State, @Binding속성 래퍼는 값 타입에서만 사용이 가능하며 두 속성 래퍼는 뷰 계층 구조에서 업데이트를 수행 합니다

이번엔 참조 유형을 다루는 방법에 대해서 알아 볼 수 있습니다

 

Working with reference types

이전에 배웠던 @State속성을 추가해서 프로퍼티를 식별했지만 구조체와 열거형 같은 값 유형에 대해서만 사용이 가능합니다

SwiftUI는 참조 유형을 Source of of truth로 선언할 수 있는 프로퍼티 래퍼를 제공하고 있습니다 :@ObservedObject, @StateObject, @EnvironmentObject

클래스에서 위에서 제시한 프로퍼티 래퍼를 사용하려면 클래스 Observable(관찰가능)하게 만들 필요가 있습니다

 

Making a class observable

클래스를 관찰 가능하게 하려면 ObservableObject 프로토콜을 채택하면 됩니다

클래스에서 변경 시에 UI Update를 트리거할 때 프로퍼티를 인식합니다 

그다음 각 속성안에 @Published 속성을 추가합니다

 

class ScrumTimer: ObservableObject {
   @Published var activeSpeaker = ""
   @Published var secondsElapsed = 0
   @Published var secondsRemaining = 0
   // ...
}

 

이 클래스는 스크럼 세션동안 업데이트되는 여러개의 @published 속성을 정의하고 있습니다

스크럼타이머는 값이 변경되므로 모든 관찰자에게 알릴 수 있습니다

 

Monitoring an object for changes

프로퍼티 선언에 다음 속성중 하나를 추가하여 SwiftUI에서 관찰 가능한 객체를 모니터링 할 수 있습니다 

ObservedObject, StateObject,EnvironmentObject 래퍼 중 하나 사용하여 선언된 뷰 속성은 뷰 계층 구조에 대한 새로운 데이터 소스를 만들게 됩니다

 

@StateObject 래퍼를 사용하면 관찰가능한 오브젝트를 생성할 수 있습니다 

앱, 씬, 뷰안에서 state object를 생성할 수 있습니다

 

이 시스템이 객체 초기화하면 해당 구조나 다른 뷰에서 사용할 수 있도록 개체를 유지하게 됩니다 

 

struct MeetingView: View {
   @StateObject var scrumTimer = ScrumTimer()
   // ...
}

 

App, Scene, View와 같은 상위 소스에서 뷰가 개체를 전달받았음을 나타내려면 @ObservedObject 속성 래퍼를 사용합니다

이러한 상위구조는 개체를 만들고 소유하기 때문에 하위 뷰에서는 ObservedObject의 초기값이 필요없습니다

 

struct ChildView: View {
   @ObservedObject var timer: ScrumTimer
   // ...
}

 

관찰 가능한 객체의 인스턴스를 View의 초기화 할 때 넘겨줍니다

 

struct MeetingView: View {
   @StateObject var scrumTimer = ScrumTimer()
   var body: some View {
      VStack {
         ChildView(timer: scrumTimer)
      }
   }
   // ...
}

복잡한 보기 계층 구조에서 관찰 가능한 개체를 공유하려면 @EnvironmentObject 속성 래퍼를 사용합니다

이니셜라이저를 통해 개체를 전달하는 대신 environment에 배치합니다 

environmentObject(_:) 뷰  수정자는 뷰의 environmentObject를 배치합니다

 

struct ParentView: View {
   @StateObject var scrumTimer = ScrumTimer()
   var body: some View {
      VStack {
         ChildView()
            .environmentObject(scrumTimer)
      }
   }
   // ...
}


struct ChildView: View {
    var body: some View {
        GrandchildView()
    }
}

 

계층 구조의 중간 뷰에 객체에 대한 참조가 없더라도 @EnvironmentObject 속성 래퍼를 사용하여 모든 하위 객체에 있는 객체에 액세스 할 수 있습니다

struct GrandchildView: View {
   @EnvironmentObject var timer: ScrumTimer
   // ...
}

@EnvironmentObject는 중간 뷰에서 불필요한 종속성을 만들지 않도록 할 수 있고 GrandParent/Parent 뷰는 모두 스크럼 타이머에 종속되고 있지만 자식 뷰에서는 그렇지 않는걸 볼 수 있습니다

 

반응형