繁体   English   中英

SwiftUI - onDeleteCommand 不适用于 macO 上的 NavigationSplitView

[英]SwiftUI - onDeleteCommand doesn't work with NavigationSplitView on macOs

我正在开发 macOs 13 应用程序,并且正在使用新的NavigationSplitView 问题是它不允许我们使用.onDeleteCommand(perform:) (或者我可能用错了)。 这是我所做的:

为了使用.onDeleteCommand(perform:) ,需要聚焦视图。 我做了一个简单的应用程序,显示了 3 个矩形,我可以使用TAB键 select,当我按下DELETE键或在菜单栏中编辑 > 删除(均触发.onDeleteCommand )时,它会切换为白色或原始颜色。

VStack {
    Rectangle()
        .fill((isColorDeleted.contains(.blue) ? Color.white : Color.blue))
        .padding()
        .focusable()
        .focused($focusedColor, equals: .blue)

    Rectangle()
        .fill((isColorDeleted.contains(.red) ? Color.white : Color.red))
        .padding()
        .focusable()
        .focused($focusedColor, equals: .red)

    Rectangle()
        .fill((isColorDeleted.contains(.yellow) ? Color.white : Color.yellow))
        .padding()
        .focusable()
        .focused($focusedColor, equals: .yellow)
}
.onDeleteCommand {
    if let focusedColor {
        if !isColorDeleted.contains(focusedColor) {
            isColorDeleted.append(focusedColor)
        } else {
            let idx = isColorDeleted.firstIndex(of: focusedColor)!
            isColorDeleted.remove(at: idx)
        }
    }
}

^^^ 这可以正常工作 ^^^

但是如果你像这样把它放在NavigationSplitView中:

NavigationSplitView(columnVisibility: $visibility) {
    List {
        Text("Main page")
    }
} detail: {
    VStack {
        Rectangle()
            .fill((isColorDeleted.contains(.blue) ? Color.white : Color.blue))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .blue)

        Rectangle()
            .fill((isColorDeleted.contains(.red) ? Color.white : Color.red))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .red)

        Rectangle()
            .fill((isColorDeleted.contains(.yellow) ? Color.white : Color.yellow))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .yellow)
    }
    .onDeleteCommand {
        if let focusedColor {
            if !isColorDeleted.contains(focusedColor) {
                isColorDeleted.append(focusedColor)
            } else {
                let idx = isColorDeleted.firstIndex(of: focusedColor)!
                isColorDeleted.remove(at: idx)
            }
        }
    }
}

如果像我解释的那样在矩形聚焦时按DELETE编辑 > 删除,它什么也没有。 事实上,编辑 > 删除根本不可点击。

您需要直接在 NavigationSplitView 上使用onDeleteCommand修饰符,如下所示:

NavigationSplitView(columnVisibility: $visibility) {
    List {
        Text("Main page")
    }
} detail: {
    VStack {
        Rectangle()
            .fill((isColorDeleted.contains(.blue) ? Color.white : Color.blue))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .blue)

        Rectangle()
            .fill((isColorDeleted.contains(.red) ? Color.white : Color.red))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .red)

        Rectangle()
            .fill((isColorDeleted.contains(.yellow) ? Color.white : Color.yellow))
            .padding()
            .focusable()
            .focused($focusedColor, equals: .yellow)
    }
}
.onDeleteCommand {
    ...
}

通过https://swiftwithmajid.com/2021/03/03/focusedvalue-and-focusedbinding-property-wrappers-in-swiftui的一些输入,我可以按如下方式解决这个问题:

  • 创建 FocusedValueKey 结构和 FocusedValues 扩展。
  • 在 NavigationSplitView 所在的视图中定义 @FocusedValue。
  • 将.onDeleteCommand 添加到 NavigationSplitView
  • 将内容/详细信息视图中的.onDeleteCommand 方法替换为.focusedValue 方法

这也适用于多个视图。 只需使用 .focusedValue 方法代替 .onDeleteCommand。 不需要进一步的参考或参数。

    import SwiftUI

    struct DeleteValueKey: FocusedValueKey {
        typealias Value = () -> Void
    }

    extension FocusedValues {
        var delete: DeleteValueKey.Value? {
            get { self[DeleteValueKey.self] }
            set { self[DeleteValueKey.self] = newValue }
        }
    }

    struct Ocean: Identifiable, Hashable {
        let name: String
        let id = UUID()
    }

    struct ContentView: View {
        
        private var oceans = [
            Ocean(name: "Pacific"),
            Ocean(name: "Atlantic"),
            Ocean(name: "Indian"),
            Ocean(name: "Southern"),
            Ocean(name: "Arctic")
        ]
        
        @FocusedValue (\.delete) var delete
        
        var body: some View {
            VStack {
                NavigationSplitView() {
                    NonWorkingView(oceans: oceans)
                } detail: {
                    WorkingView(oceans: oceans)
                }
                .onDeleteCommand(perform: delete)
            }
        }
    }

    struct NonWorkingView: View {
        
        @State var multiSelection = Set<UUID>()
        @State var oceans: [Ocean]
        
        func delete() {
            for id in multiSelection { print("\(id) deleted")}
        }
        
        var body: some View {
            List(oceans, selection: $multiSelection) {
                Text($0.name)
            }
            .onDeleteCommand(perform: delete)
            //  ^^^^^^^ DOES NOT work
        }
    }

    struct WorkingView: View {
        
        @State var oceans: [Ocean]
        @State var multiSelection = Set<UUID>()
        
        func delete() {
            for id in multiSelection { print("\(id) deleted")}
        }
        
        var body: some View {
            List(oceans, selection: $multiSelection) {
                Text($0.name)
            }
            .focusedValue(\.delete, delete)
            //  ^^^^^^^ DOES work
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM