macOS Sonoma中Swift 5.9 @Observable宏转换后进度更新异常
Swift 5.9 @Observable宏更新进度不触发视图刷新问题解决
在macOS Sonoma + Swift 5.9环境下,把旧的@StateObject/@ObservableObject换成新的@Observable宏后,大部分对象都正常工作,但有个ProgressDetails类出了问题:旧版用ObservableObject时,调用setcurrentprogress方法更新currenttaskprogress,视图能收到通知自动更新进度条;换成@Observable宏后,同样的操作却无法触发视图更新。
旧版可正常运行的代码:
final class ProgressDetails: ObservableObject, ProgressDetailsProtocol { // 存储当前任务进度 private var currenttaskprogress: Double? private var estimatedlist: [RemoteinfonumbersOnetask]? // ...其他代码 func setcurrentprogress(_ num: Double) { currenttaskprogress = num objectWillChange.send() } // ...其他代码 }
新版无法正常运行的代码:
@Observable final class ProgressDetails: ProgressDetailsProtocol { // 存储当前任务进度 var currenttaskprogress: Double? var estimatedlist: [RemoteinfonumbersOnetask]? // ...其他代码 func setcurrentprogress(_ num: Double) { currenttaskprogress = num } // ...其他代码 }
问题原因及解决方法:
1. 协议未标记@Observable(最可能原因)
如果你的视图是通过ProgressDetailsProtocol类型引用对象,而非具体的ProgressDetails类,@Observable宏生成的变更追踪逻辑无法被协议识别。解决方法是给协议加上@Observable注解:
@Observable protocol ProgressDetailsProtocol { var currenttaskprogress: Double? { get set } // 协议其他内容 }
2. 更新操作不在主线程
SwiftUI的视图更新必须在主线程触发,如果setcurrentprogress是在后台线程调用的,即使属性值变了,视图也收不到通知。修改方法是强制回到主线程更新:
func setcurrentprogress(_ num: Double) { DispatchQueue.main.async { self.currenttaskprogress = num } }
3. 视图观察方式不正确
确保视图中用正确的方式观察@Observable对象:
- 如果是视图自己创建的对象,用
@StateObject:@StateObject private var progress = ProgressDetails() - 如果是父视图传递的对象,用
@ObservedObject:
不要用协议类型作为观察对象(除非协议已经加了@ObservedObject var progress: ProgressDetails@Observable)。
额外验证方法
可以先做个简单测试:在视图里直接添加Text("\(progress.currenttaskprogress ?? 0)"),如果这个文本能随进度更新,说明属性变更逻辑没问题,问题出在进度条的绑定代码;如果文本也不更新,那就是对象的观察逻辑存在问题。
内容的提问来源于stack exchange,提问作者Tevensen
相关产品推荐
相关产品推荐

