我想使用新的 contextMenu 修饰符和“预览”,同时还支持 iOS15。我正在尝试为此创建一个ViewModifier
,以便我可以在那里进行可用性检查,但我很难在这里掌握“通用”参数的语法。
这就是我正在尝试的:
struct CompatiblityContextMenuModifier: ViewModifier {
@ViewBuilder let actionsList: Group<Any>
@ViewBuilder let actionsPreview: any View
func body(content: Content) -> some View {
if #available(iOS 16.0, *){
content
.contextMenu(menuItems: actionsList, preview: actionsPreview)
} else {
content
.contextMenu(menuItems: actionsList)
}
}
}
但编译器抱怨:
Cannot convert value of type 'any View' to expected argument type '() -> P'
Cannot convert value of type 'Group<Any>' to expected argument type '() -> M'
Generic parameter 'M' could not be inferred
Generic parameter 'P' could not be inferred
我知道我需要为 actionsList 和 actionPreview 指定不同的“类型”,但那到底是什么?
contextMenu 的函数调用如下所示:
func contextMenu<M, P>(
@ViewBuilder menuItems: () -> M,
@ViewBuilder preview: () -> P
) -> some View where M : View, P : View
“() -> M”和“() -> P”到底是什么
以下是到目前为止我所拥有的。为了将
View
其作为参数合并到 中ViewModifier
,您需要一种特定的技术。 这个主题很有帮助。在这种情况下,您必须合并两组View
,我通过反复试验以某种方式管理了它们。以下是我在 iOS 16 上测试的方法。
View 和 Group 与 contextMenu 期望的类型不直接兼容。此外,SwiftUI 的 contextMenu 修饰符不接受 Group 作为其 menuItems 参数。相反,它期望一个返回一些视图的闭包。
要解决此问题并创建通用 ViewModifier,您可以对 actions 闭包使用 @ViewBuilder 属性,并为符合 View 的预览使用通用类型占位符。您可以这样做:
}
当您使用 iOS 16 或更高版本时,您可以为菜单项提供关闭,也可以选择为预览提供关闭:
}
通过这种方式,您可以提供一个返回菜单项的闭包,并且有条件地提供一个返回预览内容的闭包。这应该可以正确编译并在 iOS 15 和 iOS 16 上为您提供所需的行为。