SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject

Posted

技术标签:

【中文标题】SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject【英文标题】:SwiftUI - Observable Object initiated from Swift class does not update @ObservedObject on ContentView() 【发布时间】:2020-07-29 11:53:01 【问题描述】:

ObservableObject 类是从 ContentView() 和另一个 Swift 类实例化的。 ObservableObject类的函数在Swift类运行时,不会更新ContentView()的@ObservedObject。

我知道这是因为我两次实例化了 ObservableObject 类。当 Observable 类没有/不能被 ContentView() 实例化时,使用 @ObservedObject 的最佳做法是什么。

我还没有找到让@EnvironmentObject 与 Swift 类一起使用的方法。 我可以使用全局变量并运行 Timer() 来检查对它的更改。然而,这感觉像是一种丑陋的做法?!?

请参阅下面的示例代码。请在设备上运行,查看打印语句。


import SwiftUI

struct ContentView: View 
    
    @ObservedObject var observedClass: ObservedClass = ObservedClass()
    
    // The callingObservedClass does not exist on the ContentView, but is called
    // somewhere in the app with no reference to the ContentView.
    // It is included here to better showcase the issue.
   
    let callingObservedClass: CallingObservedClass = CallingObservedClass()
    
    var body: some View 
        
        VStack 
   
            // This Text shall be updated, when
            // self.callingObservedClass.increaseObservedClassCount() has been executed.
   
            Text(String(observedClass.count))
            
            Button(action: 
    
                // This updates the count-variable, but as callingObservedClass creates
                // a new instance of ObservedClass, the Text(observedClass.count) is not updated.
   
                self.callingObservedClass.increaseObservedClassCount()
            , label: 
                Text("Increase")
            )
        
    



class CallingObservedClass 
    
    let observedClass = ObservedClass()
    
    func increaseObservedClassCount() 
   
        // Returning an Int here to better showcase that count is increased.
        // But not in the ObservedClass instance of the ContentView, as the
        // Text(observedClass.count) remains at 0.
    
        let printCount = observedClass.increaseCount()
        print(printCount)
    



class ObservedClass: ObservableObject 
    @Published var count: Int = 0
    
    func increaseCount() -> Int 
        count = count + 1
        return count
    



struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    


编辑:我想我的问题是当我无法从 SwiftUI 视图实例化 Swift 类时,如何从 Swift 类获取数据并更新 SwiftUI 视图。

【问题讨论】:

【参考方案1】:

一个可能的解决方案是链接 ObservableObject 类。不幸的是,从 ios 13.6 开始,这不能开箱即用。

我通过以下方式找到了答案: How to tell SwiftUI views to bind to nested ObservableObjects

调整和运行示例:

// Add Combine

import Combine
import SwiftUI

struct ContentView: View 

    @ObservedObject var callingObservedClass: CallingObservedClass = CallingObservedClass()
    
    var body: some View 
        
        VStack 

            // Calling the chained ObservableObject
            
            Text(String(callingObservedClass.observedClass.count))
            
            Button(action: 

                self.callingObservedClass.increaseObservedClassCount()
            , label: 
                Text("Increase")
            )
        
    


class CallingObservedClass: ObservableObject 
    
    // Chaining Observable Objects
    
    @Published var observedClass = ObservedClass()
    
    // ObservableObject-chaining does not work out of the box.
    // The anyCancellable variable with the below init() will do the trick.
    // Thanks to https://***.com/questions/58406287/how-to-tell-swiftui-views-to-bind-to-nested-observableobjects
    
    var anyCancellable: AnyCancellable? = nil
    
    init() 
        anyCancellable = observedClass.objectWillChange.sink  (_) in
            self.objectWillChange.send()
        
    
    
    func increaseObservedClassCount() 
        let printCount = observedClass.increaseCount()
        print(printCount)
    


class ObservedClass: ObservableObject 
    @Published var count: Int = 0
    
    func increaseCount() -> Int 
        count = count + 1
        return count
    



struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    

如果 ObservableObject-Chaining 不是一个选项,我对如何访问 Swift 类数据和更新 SwiftUI 视图很感兴趣。

如果您对此有解决方案,请在下面回答。

【讨论】:

以上是关于SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI-> 线程 1:致命错误:未找到 MyObject.Type 类型的可观察对象(工作表中的 EnvironmentObject)

将数据从委托 Swift 类传递到 SwiftUI 结构中的 EnvironmentObject

Combine + SwiftUI 中的最佳数据绑定实践?

Xcode 11 中 Swift Combine.framework 的可选链接

已发布值上的 SwiftUI toggle() 函数停止使用 Swift 5.2 触发 didSet

如何在 SwiftUI 中使用可观察对象并与 NavigationLink 绑定?