You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@Observable修饰类后为何需显式声明ObservableObject协议?

关于@Observable与ObservableObject的疑问解答

核心问题拆解与解答

1. @Observable修饰的类是否隐式符合ObservableObject?

是的,@Observable宏会自动让类隐式遵循ObservableObject协议,它会生成协议要求的objectWillChange发布者等必要实现。问题出在编译器的类型检查逻辑上,而非协议一致性本身。

2. 为什么Swift需要显式声明才能让environmentObject识别?

environmentObject(_:)是基于Combine框架的旧API,它的参数类型明确要求是ObservableObject。Swift编译器在处理这种显式类型约束的方法调用时,不会自动推导@Observable类的隐式协议一致性——只有当你显式声明class ApplicationData: ObservableObject时,编译器才会直接匹配到ObservableObject类型,通过检查。

3. 书中示例未添加ObservableObject是否合理?

这要看书籍对应的技术版本:

  • @Observable是iOS 17/macOS 14及以上引入的Observation框架新特性,而environmentObject属于旧的Combine生态API。如果书籍编写时Observation框架刚推出,可能没考虑到编译器类型检查的这个细节;
  • 更合理的新写法应该搭配Observation框架的environment(_:)API,而非旧的environmentObject(_:),这样完全不需要显式声明ObservableObject。

4. 同时使用@Observable宏和ObservableObject协议是否为最佳实践?

不是最佳实践。两者分属新的Observation框架和旧的Combine观察机制,同时使用属于冗余操作。推荐的标准写法是:

  • 只用@Observable修饰类,无需显式遵循ObservableObject
  • 使用新的环境传递API:.environment(appData)
  • 在子视图中通过@Environment(ApplicationData.self)获取实例

修正后的代码示例

import SwiftUI
import Observation

@Observable class ApplicationData {
    var title: String = "Default Title"
}

@main
struct TestApp: App {
    @State private var appData = ApplicationData()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(appData) // 使用Observation框架配套的environment API
        }
    }
}

// 子视图获取实例的方式
struct ContentView: View {
    @Environment(ApplicationData.self) private var appData
    
    var body: some View {
        Text(appData.title)
    }
}

内容的提问来源于stack exchange,提问作者Purp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:02:13