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

SwiftUI中@Observable属性适配.onReceive()的问题咨询

问题解决:在@Observable属性上使用.onReceive()

错误原因

你遇到的错误是因为.onReceive(_:perform:)要求接收的参数必须遵循Publisher协议,但myData.isReady是Bool类型,并不符合这个要求,所以编译器报错。

实现.onReceive()的可行方案

在@Observable类中,单个属性默认不会自动成为Publisher,但你可以通过Combine框架的CurrentValueSubject(或PassthroughSubject)将属性封装为Publisher,从而适配.onReceive()的要求。

步骤1:修改可观察对象类

将isReady替换为CurrentValueSubject<Bool, Never>类型,它本身就是一个Publisher,可以发送值的变化:

import Combine
import Observation

@Observable
class MyObservableObject {
    // 用CurrentValueSubject包装Bool值,初始值设为false
    var isReady = CurrentValueSubject<Bool, Never>(false)
    var isDoneFetching = false
    
    func fetchStuff() {
        // 模拟异步数据请求
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.isDoneFetching = true
            // 发送isReady状态更新
            self.isReady.send(true)
        }
    }
}

步骤2:在视图中使用.onReceive()

现在myData.isReady是合法的Publisher,可以直接传入.onReceive():

private var myData = MyObservableObject()

VStack {
    // 视图内容
}
.onAppear {
    myData.fetchStuff()
}
.onReceive(myData.isReady) { isReady in
    if isReady {
        formatUIData()
    }
}

补充说明

  • CurrentValueSubject会保存当前值,新订阅者会立即收到最新值;如果不需要保存当前值,可改用PassthroughSubject。
  • 如果你不想引入Combine的Subject,也可以通过myData.objectWillChange(@Observable类自带的Publisher)监听整个对象的变化,但这会在任意属性更新时触发,不如单个属性的Subject精准。

内容的提问来源于stack exchange,提问作者William T.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:44:55