使用Toolbar Picker与keyboardShortcut时ObservedObject状态滞后问题排查
问题分析与解决
问题现象
- 切换选中的Host后,点击ConsoleView中的执行按钮,偶尔会打印上一次选中的Host名称(已通过
.id(host)或.help()临时修复); - 使用
Cmd+Return快捷键触发执行时,首次会打印上一次的Host名称,需要触发两次才会显示当前选中值。
核心原因
- 视图身份与生命周期问题:当
selectedHost切换时,SwiftUI可能没有完全重建ConsoleView,导致Toolbar中的按钮/快捷键仍绑定着旧的RemoteHost实例; - 快捷键绑定位置错误:你将
keyboardShortcut修饰在了ToolbarItem层级而非按钮本身,导致快捷键注册没有随按钮的更新而同步刷新。
解决方案
1. 强制ConsoleView随Host切换完全重建
在创建ConsoleView时添加.id(selectedHost),让SwiftUI在selectedHost变化时销毁旧视图并创建新实例:
case .console: ConsoleView(host: selectedHost) .id(selectedHost) // 添加该行强制视图重建
2. 修正快捷键绑定位置
将keyboardShortcut直接修饰在按钮上,确保每次按钮随Host更新时,快捷键绑定同步更新:
ToolbarItem { Button { print("exec against host: \(host.name)") } label: { Label("Execute", systemImage: "play.circle") } .keyboardShortcut(.return, modifiers: .command) // 移至Button层级 }
3. 可选优化:让RemoteHost遵循Equatable
为RemoteHost添加Equatable协议实现,帮助SwiftUI更精准地判断实例变化:
class RemoteHost: ObservableObject, Equatable { @Published var name: String static func == (lhs: RemoteHost, rhs: RemoteHost) -> Bool { lhs.name == rhs.name // 若有其他属性,需补充对应比较逻辑 } // 初始化及其他代码... }
完成以上调整后,无论是按钮点击还是快捷键触发,都能正确获取当前选中的Host实例。
内容的提问来源于stack exchange,提问作者Max Zhang
相关产品推荐
相关产品推荐

