macos - 如何使用 FocusedValues 将子视图状态链接到菜单
问题描述
SwiftUI 新手在这里。在为 MacOS 应用程序构建菜单时,我很难理解如何@FocusedBinding
和工作。FocusedValues
我正在尝试使用窗口工具栏中的按钮构建Apple HIG UI 模式,以更改列表视图并匹配视图菜单中的菜单项。就像 Finder 窗口有四种不同的视图模式一样。
我已经阅读了Apple 的 Landmarks 教程、Apple 开发论坛中的 Frameworks Engineer 的示例代码和Majid 的教程。
苹果文档说FocusedValues
是“由焦点视图及其祖先导出的状态集合”。我假设集合是全局的,我可以focusedValue
在任何子视图中设置 a,并从我的代码中的任何位置读取或绑定到任何 FocusedValues。
因此,我不明白为什么下面的第一个示例有效,而第二个示例无效?
这有效:
import SwiftUI
@main
struct TestiApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.frame(minWidth: 200, minHeight: 300)
.onAppear {
NSWindow.allowsAutomaticWindowTabbing = false
}
}
.windowStyle(HiddenTitleBarWindowStyle())
.commands {
MenuCommands()
}
}
}
struct ContentView: View {
// In the working version of the code selectedView is defined here
// in the ContentView, which is a direct child of the WindowGroup
// that has the .commands modifier.
@State private var selectedView: Int = 0
// For demonstration purposes I have simplified the authorization
// code to a hardcoded boolean.
private var isAuthorized: Bool = true
var body: some View {
switch isAuthorized {
case true:
// focusedValue is set here to the selectedView binding.
// I don't really understand why do it here, but it works.
AuthorizedView(selectedView: $selectedView)
.focusedValue(\.selectedViewBinding, $selectedView)
default:
NotYetAuthorizedView()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct AuthorizedView: View {
// selectedView is passed to this view as an argument and
// bound from ContentView.
@Binding var selectedView: Int
var body: some View {
List {
Text("Something here")
Text("Something more")
Text("Even more")
}
.toolbar {
// The Picker element sets and gets the bound selectedView value
Picker("View", selection: $selectedView) {
Text("View 1").tag(0)
Text("View 2").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
struct NotYetAuthorizedView: View {
var body: some View {
VStack {
Text("You need permission to access this ")
.padding()
}
}
}
struct MenuCommands: Commands {
private struct MenuContent: View {
// Command menu binds the selectedView value through focusedValues.
// MenuContent is a View, because otherwise the binding doesn't
// work (I read there's a bug in SwiftUI...).
@FocusedBinding(\.selectedViewBinding) var selectedView: Int?
var body: some View {
Button("View 1") {
selectedView = 0
}
.keyboardShortcut("1")
Button("View 2") {
selectedView = 1
}
.keyboardShortcut("2")
}
}
var body: some Commands {
CommandGroup(before: .toolbar) {
MenuContent()
}
}
}
struct SelectedViewBinding: FocusedValueKey {
typealias Value = Binding<Int>
}
extension FocusedValues {
var selectedViewBinding: SelectedViewBinding.Value? {
get { self[SelectedViewBinding.self] }
set { self[SelectedViewBinding.self] = newValue }
}
}
但是,如果我对 ContentView 和 AuthorizedView 进行以下更改,则项目可以正常编译,但selectedView
命令菜单和命令菜单之间的绑定不再起作用:
struct ContentView: View {
// selectedView definition has been removed from ContentView
// and moved to AuthorizedView.
private var isAuthorized: Bool = true
var body: some View {
switch isAuthorized {
case true:
AuthorizedView()
// Also setting the focusedValue here has been removed
default:
NotYetAuthorizedView()
}
}
}
struct AuthorizedView: View {
// Moved selectedView definition here
@State private var selectedView: Int = 0
var body: some View {
List {
Text("Something here")
Text("Something more")
Text("Even more")
}
.toolbar {
Picker("View", selection: $selectedView) {
Text("View 1").tag(0)
Text("View 2").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.focusedValue(\.selectedViewBinding, $selectedView)
// I am now setting the focusedValue here, which seems
// more logical to me...
}
}
}
我更喜欢第二个例子,因为selectedView
状态被封装在AuthorizedView
它所属的地方。
解决方案
推荐阅读
- python - 如何阅读 django 调试器给我的这一行?(无反向匹配)
- ios - iOS Rxswift 处理 CancelButton 点击 searchBar
- ios - IOS/Storyboard:图像在长时间重做后从身份检查器中消失,但在 Storyboard 中仍然可见
- react-native - 在 react native 中链接只能打开一个应用
- python - 具有子数组和可变长度的 numpy 关联数组的最佳生成
- java - 生物特征认证java应用程序。如何在智能手机和应用程序之间建立连接
- redux - mapDispatchToProps 函数未定义
- python-3.x - 在 Masonite 中在哪里更改 HTTP 端口设置?
- aggregate - R中每天的日夜平均值
- objective-c - 从 HTMLKit 中的 HTMLDocument 获取 href