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

SwiftUI修改@Published属性无法触发UI更新,如何解决?

问题与解决方案

问题描述

我正在开发一款应用,添加了一个TextEditor字段,用于显示应用文档Model对象中@Published修饰的text属性内容。

Model对象相关代码:

final class DrawingInfo: ObservableObject, Codable {
    // Items saved with Codable
    @Published var title: String
    @Published var text: String
    @Published var toggleIsOn: Bool = false
    let imageSize: CGSize
    @Published var backgroundColor = Color.white
    @Published var texAspect: Float = 1.0
    @Published var linePlacement: Float = 0

    // ...
}

ContentView代码:

var body: some View {
    VStack {
        VStack {
            DrawingView(drawingInfo: $drawingInfo)
                .frame(width: DrawingInfo.defaultSize.width, height: DrawingInfo.defaultSize.height)
                .border(Color.blue, width: 4)
                .aspectRatio(drawingInfo.imageSize, contentMode: .fit)
            TextEditor(text: $drawingInfo.text)
                .frame(maxHeight: 50)
            HStack {
                Button("Test") {
                    drawingInfo.text += " Extra words."
                }

                Toggle(isOn: $drawingInfo.toggleIsOn) {
                    Text("Toggle is on")
                }
                .frame(maxWidth: 200, alignment: toggleAlignment)

                Slider(value: $drawingInfo.linePlacement, in: -1...1) {
                    
                }
                .frame(maxWidth: 200)
            }
        }
    }
}

点击“Test”按钮时,会向model的text属性追加字符串“ Extra words.”,但TextEditor不会立即更新,直到修改其他@Published属性(如点击Toggle或调整Slider)才会刷新。推测是因为按钮闭包直接修改text属性,而非通过model的绑定进行更改,想知道如何修改按钮闭包让TextEditor能实时响应text属性的变化?是否需要设置Combine发布者来触发更新?

解决方案

不需要额外设置Combine发布者,两种简单修改方式即可解决:

方式一:通过绑定的wrappedValue修改

直接使用$drawingInfo.text的绑定对象来修改值,确保发布事件被SwiftUI正确捕获:

Button("Test") {
    $drawingInfo.text.wrappedValue += " Extra words."
}

方式二:在Model内封装修改方法

在DrawingInfo类中添加专门的方法来修改text,这种方式更符合MVVM的封装原则,同时能确保更新事件正常触发:

final class DrawingInfo: ObservableObject, Codable {
    // 原有属性...

    func appendToText(_ string: String) {
        text += string
        // 若@Published未自动触发更新(极少出现),可手动调用以下代码强制触发:
        // objectWillChange.send()
    }
}

然后在按钮闭包中调用该方法:

Button("Test") {
    drawingInfo.appendToText(" Extra words.")
}

原因解析

直接修改drawingInfo.text时,虽然@Published会自动发送变更事件,但在某些场景下,SwiftUI可能未正确追踪到该属性的绑定关联,导致视图未及时刷新。通过绑定对象修改或封装方法,能确保变更事件被SwiftUI正确识别,从而实时更新TextEditor的显示内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 01:42:31