SwiftUI macOS中子视图设置的FocusedValues为何无法绑定菜单命令
问题原因
FocusedValues的核心生效规则:只有添加了.focusedValue修饰符的视图位于当前焦点响应链上(即该视图本身或其子视图处于第一响应者状态)时,你设置的值才会被系统注入到全局可读取的FocusedValues集合中。- 第二种写法失效的核心原因是把
.focusedValue修饰符添加到了工具栏的Picker上:工具栏控件默认不会成为第一响应者,日常使用时窗口的焦点通常落在内容区的List上,此时Picker不在焦点响应链上,你设置的绑定值自然无法被@FocusedBinding读取,菜单绑定就会失效。
解决方案
不需要把状态提升到ContentView,只需要把.focusedValue修饰符从Picker移到AuthorizedView的根内容视图上即可,修改后的AuthorizedView代码如下:
struct AuthorizedView: View { // selectedView依然封装在内部,符合你的架构要求 @State private var selectedView: Int = 0 var body: some View { List { Text("Something here") Text("Something more") Text("Even more") } // 修饰符加在内容区根视图上,只要当前窗口内容区处于激活状态,该值就会生效 .focusedValue(\.selectedViewBinding, $selectedView) .toolbar { Picker("View", selection: $selectedView) { Text("View 1").tag(0) Text("View 2").tag(1) } .pickerStyle(SegmentedPickerStyle()) } } }
逻辑说明
- 内容区的
List是窗口激活时默认的第一响应者所在视图,你在List上添加的focusedValue会一直处于焦点响应链中,菜单的@FocusedBinding可以正常读取到绑定值。 - 该写法完全支持多窗口场景:每个窗口的
AuthorizedView持有独立的selectedView状态,切换激活窗口时FocusedValues会自动更新为当前窗口对应的值,完美匹配Finder的多窗口独立视图切换逻辑。
内容的提问来源于stack exchange,提问作者Niko Nyman
相关产品推荐
相关产品推荐

