Xcode报错:Publishing changes from within view updates is not allowed, this will cause undefined behavior.
Xcode报错:Publishing changes from within view updates is not allowed, this will cause undefined behavior.

Xcode报错:Publishing changes from within view updates is not allowed, this will cause undefined behavior.

SwiftUI在视图更新阶段,如果尝试修改@Published / @StateObject / @ObservedObject 所管理的状态,就会弹出警告提示。

例如,Swift代码:

class CustomImages: ObservableObject {
    @Published var inputURL: URL   // 输入URL
    @Published private var _inputSize: Int?   // 文件输出大小
    
    // 输入文件的大小
    var inputSize: Int {
        if _inputSize == nil {
            _inputSize = FileUtils.getFileSize(fileURL: inputURL)   // 报错代码行
        }
        return _inputSize ?? 0
    }
}

这个类中,inputSize是一个计算属性,如果 inputSize 变量为nil,就会计算输入文件的大小,并赋值给 _inputSize 变量。

但是,Xcode在赋值代码行中会提示:

Publishing changes from within view updates is not allowed, this will cause undefined behavior.

因为,SwiftUI 明确禁止,在视图更新过程中发布状态变更。因此产生这个提示信息。

计算属性应该是纯函数(无副作用),如果涉及读取状态、计算I/O、修改状态(触发objectWillChange),就会破坏SwiftUI的渲染事物一致性,导致无限刷新、状态错乱以及UI Bug等问题。

解决方案

1、懒加载逻辑移除计算属性

将计算属性中的修改属性状态代码改为方法,在SwiftUI中调用方法。

func loadInputSizeIfNeeded() {
    guard _inputSize == nil else { return }
    _inputSize = FileUtils.getFileSize(fileURL: inputURL)
}

// SwiftUI 中显示
.onAppear {
    image.loadInputSizeIfNeeded()
}

计算属性,仅用于读取数据:

var inputSize: Int {
    return _inputSize ?? 0
}

2、使用 lazy

lazy var inputSize: Int = {
    FileUtils.getFileSize(fileURL: inputURL)
}()

lazy 不适用于 SwiftUI 状态对象,这里并不适用。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注