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

SwiftUI 如何修改ListView选中状态的勾选图标 选中后UI不更新如何解决

问题根因

UI未同步刷新的核心原因有两点:

  • Todo是引用类型(Class),@State仅能监听值类型的整体变更,你修改Todo实例的completed属性时,items数组存储的元素引用没有发生变化,@State无法检测到变更,不会触发视图重绘。
  • 子视图Row接收的item为不可变的let常量,没有内置的监听机制响应属性变更。

解决方案1:将Todo改为值类型(推荐)

绝大多数待办场景下用结构体更符合SwiftUI的设计理念,改动最小,性能最优:

// 将Todo从Class改为Struct
struct Todo: Hashable {
    var title: String
    var completed: Bool
}

// 调整ContentView的遍历逻辑为绑定遍历
struct ContentView: View {
    @State var items: [Todo] = todoItems
    
    var body: some View {
        List($items) { $item in
            Row(item: item) {
                item.completed.toggle()
                print(item.completed)
            }
        }
    }
}

// 简化Row的回调逻辑
struct Row: View {
     let item: Todo
    var onTap: (() -> Void)?
    
    var body: some View {
        HStack {
            Image(systemName: item.completed ? "checkmark.square.fill" :  "squareshape" )
                .foregroundColor(item.completed ? .green : .gray)
            Text(item.title).font(.headline).foregroundColor(.secondary)
        }.onTapGesture {
            onTap?()
        }
    }
}

// 全局待办数据对应调整
let todoItems = [
    Todo(title: "$300", completed: false),
    Todo(title: "$550", completed: false),
    Todo(title: "$450", completed: false)
]

解决方案2:保留Class的适配方案

如果业务必须保留Todo为Class类型,需要搭配SwiftUI的对象监听协议实现刷新:

// Todo遵循ObservableObject协议,需要监听的属性加@Published注解
class Todo: Hashable, ObservableObject {
    static func == (lhs: Todo, rhs: Todo) -> Bool {
        lhs.title == rhs.title
    }
    
    var title: String
    @Published var completed: Bool
    
    init(title: String, completed: Bool) {
        self.title = title
        self.completed = completed
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(title)
    }
}

// Row用@ObservedObject接收Todo实例,监听属性变更
struct Row: View {
     @ObservedObject var item: Todo
    var onTap: (() -> Void)?
    
    var body: some View {
        HStack {
            Image(systemName: item.completed ? "checkmark.square.fill" :  "squareshape" )
                .foregroundColor(item.completed ? .green : .gray)
            Text(item.title).font(.headline).foregroundColor(.secondary)
        }.onTapGesture {
            onTap?()
        }
    }
}

// ContentView无需额外调整
struct ContentView: View {
    @State var items: [Todo] = todoItems
    
    var body: some View {
        List(items, id: \.self) { item in
            Row(item: item) {
                item.completed.toggle()
                print(item.completed)
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:21:04