我想为'contextMenu forSelectionType: menu:'添加iOS16 API,但我还需要支持iOS15,所以我需要一个条件
ViewModifier
。我正在努力寻找正确的语法。
据我所知,我的
ViewModifier
应该是这样的:
struct CompatibilityListContextMenuModifier<V>: ViewModifier where V: View {
let menu: (Set<Person.ID>) -> V
func body(content: Content) -> some View {
if #available(iOS 16.0, macOS 13.0, *) {
content
.contextMenu(forSelectionType: Person.ID.self, menu: menu)
} else {
content
}
}
}
但是我如何在我的列表中使用它:
List (selection: $contactsListOptions.multiSelectedContacts){
// ...
}
.modifier(CompatibilityListContextMenuModifier(menu: items in {
if items.isEmpty { // Empty area menu.
Button("New Item") { }
} else if items.count == 1 { // Single item menu.
Button("Copy") { }
Button("Delete", role: .destructive) { }
}
else {
Button("MultipleSelection Items") { }
}
}))
这给了我一个语法错误:
在范围内找不到“项目”
如果我尝试传入选择绑定:
.modifier(CompatibilityListContextMenuModifier(menu: contactsListOptions.multiSelectedContacts in {
if contactsListOptions.multiSelectedContacts.isEmpty { // Empty area menu.
Button("New Item") { }
} else if contactsListOptions.multiSelectedContacts.count == 1 { // Single item menu.
Button("Copy") { }
Button("Delete", role: .destructive) { }
}
else {
Text("MultipleSelection Items")
}
}))
我收到错误:
无法将“Set
”类型(又名“Set”)的值转换为 预期参数类型 '(Set ) -> V' (又名 '(Set) -> V')
和
无法推断通用参数“V”
条件编译此 API 的正确方法是什么?
创建修饰符的语法应该是:
CompatibilityListContextMenuModifier { items in ... }
闭包参数应位于
{ ... }
内部。
闭包也应该是一个
@ViewBuilder
,否则你不能在闭包中使用像这样的 if
语句。
// I also abstracted away Person.ID as the Selection type parameter
struct CompatibilityListContextMenuModifier<Menu, Selection>: ViewModifier
where Menu: View, Selection: Hashable {
@ViewBuilder
let menu: (Set<Selection>) -> Menu
func body(content: Content) -> some View {
if #available(iOS 16.0, macOS 13.0, *) {
content
.contextMenu(forSelectionType: Selection.self, menu: menu)
} else {
content
}
}
}
现在你可以像这样使用它:
.modifier(CompatibilityListContextMenuModifier<_, Person.ID> { items in
if items.isEmpty {
Button("New Item") { }
} else if items.count == 1 {
Button("Copy") { }
Button("Delete", role: .destructive) { }
}
else {
Button("MultipleSelection Items") { }
}
})
我还建议您编写自己的
View
扩展,以便更方便地编写此内容:
extension View {
func compatibilityContextMenu<Menu: View, Selection: Hashable>(
forSelectionType type: Selection.Type,
@ViewBuilder menu: @escaping (Set<Selection>) -> Menu
) -> some View {
modifier(CompatibilityListContextMenuModifier(menu: menu))
}
}
.compatibilityContextMenu(forSelectionType: Person.ID.self) { items in
// ...
}