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

SwiftUI中.contextMenu切换Bool值后按钮文本未更新如何解决

问题原因

SwiftUI 的 .contextMenu 会在所属视图首次渲染时预生成菜单内容,后续状态变更时默认不会触发菜单的重建,因此修改 active 字段后,已生成的上下文菜单文本不会自动更新。

解决方案

给挂载 .contextMenu 的视图添加 .id() 修饰符,将 item.active 作为标识的一部分,只要该值发生变化,SwiftUI 就会销毁旧视图、重新渲染新视图,同步重新生成最新的上下文菜单。
同时建议将 ForEach 遍历改为绑定遍历,避免手动查找索引带来的强制解包风险,修改后的完整代码如下:

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let user: String
    var active: Bool
}

struct ContentView: View {
    @State var items: [Item] = [
        Item(user: "Daniel",active: false),
        Item(user: "Jack", active: true),
        Item(user: "John", active: true)
    ]
    
    var body: some View {
        List {
            // 改为绑定遍历,直接拿到元素的可修改引用
            ForEach($items) { $item in
                VStack {
                    Text("\(item.user)")
                        
                    HStack {
                        Text("Active ? ")
                        Text(item.active ? "YES": "NO")
                    }
                }
                // 新增id修饰符,active变化时触发视图重绘刷新contextMenu
                .id(item.active)
                .contextMenu{
                    Button(action: {
                        // 直接通过绑定修改状态,无需手动查找索引
                        item.active.toggle()
                    }) {
                        Text(item.active ? "设为未激活": "设为已激活")
                    }
                }
            }
        }
    }
}

上述方案实现成本最低,对原有业务逻辑几乎无侵入。如果不想修改视图标识,也可将上下文菜单内容单独封装为接收状态绑定的子视图,同样能实现菜单的自动更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:45:05