如何在SwiftUI视图外访问@StateObject修饰的ObservableObject实例
问题核心原因
- 实例不统一:你已经定义了
WatchlistClass的单例shared,但WatchlistView中直接初始化了新的WatchlistClass实例,导致视图持有的实例和全局单例不是同一个对象,两边数据完全独立,所以会出现访问不到对应数据的问题。 - Timer闭包捕获错误:Timer作为存储属性直接初始化时,闭包捕获的
self还未完成初始化,同时默认强引用会导致循环引用,无法正确访问watchlist属性。 - @Published不支持修饰静态属性,所以你给
watchlist加static修饰符会触发编译错误,不需要通过静态属性实现全局访问。
解决方案
步骤1:统一使用单例实例,避免多实例数据不同步
首先将WatchlistClass的初始化方法设为私有,从根源禁止外部创建新实例,保证全局只有shared这一个实例:
class WatchlistClass: ObservableObject { static let shared = WatchlistClass() // 私有初始化方法,禁止外部创建新实例 private init() {} @Published var watchlist: [StockInformation] = [] // 其余原有代码... }
然后修改视图层的@StateObject声明,直接绑定单例:
struct WatchlistView: View { @StateObject var watchlistClass = WatchlistClass.shared // 其余原有代码... }
后续你在任意位置需要读写watchlist数据,都可以直接通过WatchlistClass.shared.watchlist操作,所有绑定了该单例的视图都会自动触发刷新。
步骤2:修正Timer的实现,解决访问问题
将Timer的初始化移到类的私有初始化方法中,使用[weak self]弱引用捕获self,避免循环引用和访问错误:
class WatchlistClass: ObservableObject { static let shared = WatchlistClass() @Published var watchlist: [StockInformation] = [] // 先声明可选Timer属性,不在定义时直接初始化 private var timer: Timer? private init() { // 在初始化方法中创建Timer,用弱引用捕获self timer = Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true) { [weak self] _ in guard let self = self else { return } if !self.watchlist.isEmpty { // 你的定时业务逻辑 } } } // 类销毁时停止Timer,避免内存泄漏 deinit { timer?.invalidate() } // 其余原有代码... }
内容的提问来源于stack exchange,提问作者llizatovic.main.developer
相关产品推荐
相关产品推荐

