【SwiftUI】ObservedObject 안에 넣은 클래스의 변경으로 View를 갱신하고 싶을 때의 주의

10625 단어 SwiftSwiftUI
ObservedObject 안에 데이터 클래스를 넣고 그 업데이트를 얻으려고하면 빠졌기 때문에 공유
분명히이 사건은이 상태에서 View가 업데이트되지 않는 모양입니다.
(만약 잘못되었거나 이런 방법도 있다고 하는 것이 있으면 대응하므로 가르쳐 주시면 다행입니다!)

실험



초당 1씩 증가하는 subCount를 가진 DataClass 만들기

DataClass
class DataClass: ObservableObject {
    @Published var subCount = 0
    var timer = Timer()

    init(){
        //生成と共にタイマー開始
        timer =  Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(classLoop), userInfo: nil, repeats: true)
    }
    // タイマーで呼び出されるメソッド
    @objc func classLoop() {
        subCount = subCount + 1
    }
}

 
5초에 1씩 늘어나는 rootCount와 이전 DataClass를 가진 PublishTest도 만듭니다

DataClass가 있는 PublishTest
class PublishTest: ObservableObject {
    @Published var rootCount: Int = 0
    @Published var dataclass = DataClass()

    var timer = Timer()

    init(){
        //生成と共にタイマー開始
        timer =  Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(classLoop), userInfo: nil, repeats: true)
        }
    }
    // タイマーで呼び出されるメソッド
    @objc func classLoop() {
        rootCount = rootCount + 1
    }
}

마지막으로 View측은 아래와 같이 표시합니다
  • publishTest 자신의 rootCount
  • publishTest가 가지는 DataClass의 subCount

  • View측
    struct ContentView: View {
    
        @ObservedObject var publishTest: PublishTest
    
        var body: some View {
            VStack{
                Text("rootCountは\(publishTest.rootCount)")
                Text("DataClassのsubCountは\(publishTest.dataclass.subCount)")
            }
        }
    }
    

    결과





    잠시 업데이트되지 않음
    또한 print로 로그를 보면 subCount가 증가하고 있는지 확인할 수 있습니다.


    5초가 지나면 rootCount가 업데이트되면 rootCount도 subCount도 해당 시점으로 업데이트됩니다.

    아무것도 하지 않으면 아래의 동작이 되는 것 같습니다.
  • ObservedObject 안에 중첩 된 서브 클래스 측의 변경은 View 측에 전해지지 않는다
  • ObservedObject 바로 아래의 무엇인가가 갱신되었을 때 View가 갱신되어 서브 클래스의 데이터도 반영

  • 대응책



    1.ObservedObject 바로 아래의 데이터를 이용하는 구조로 한다



    몸도 뚜껑도 없습니다만, View측에서 갱신시키고 싶은 것은 모두 ObservedObject직하의 것만을 사용하는 구조로 하는 것이 1개.
    혹은 갱신시키고 싶은 타이밍으로 ObservedObject의 데이터를 강제적으로 갱신하는 일도 실현은 가능할지도 모릅니다(위의 실험의 경우)

    2. Combine의 objectWillChange를 이용한다



    Combine의 objectWillChange를 이용하는 것으로 데이터의 갱신이 반영되는 것 같습니다.
    이 기사가 도움이되었습니다.
    https://www.it-swarm-ko.com/en/ios/%E5%85%A5%E3%82%8C%E5%AD%90%E3%81%AB%E3%81%AA%E3 %81%A3%E3%81%9Fobservableobject%E3%81%AB%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89%E3%81%99%E3%82 %8B%E3%82%88%E3%81%86%E3%81%ABswiftui%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AB%E6%8C%87 %E7%A4%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/813692063/

    PublishTest 측에 추가해 보겠습니다.

    DataClass가있는 PublishTest (업데이트)
    import Combine
    
    class PublishTest: ObservableObject {
        @Published var rootCount: Int = 0
        @Published var dataclass = DataClass()
        var timer = Timer()
    
        var anyCancellable: AnyCancellable? = nil   //追加
    
    
        init(){
            timer =  Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(classLoop), userInfo: nil, repeats: true)
    
            //追加ここから
            anyCancellable = dataclass.objectWillChange.sink { (_) in
                self.objectWillChange.send()
            }
            //追加ここまで
        }
    
        // タイマーで呼び出されるメソッド
        @objc func classLoop() {
            rootCount = rootCount + 1
        }
    }
    

    이제 업데이트되었는지 확인

    좋은 웹페이지 즐겨찾기