[英]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的一些输入,我可以按如下方式解决这个问题:
这也适用于多个视图。 只需使用 .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.