我开始喜欢使用SwiftUI编写跨平台UI代码的方法。该应用程序仍将使用本机窗口/容器启动,但具有完全跨平台的SwiftUI驱动的UI。对于许多标准的东西,例如列表,导航视图等,它非常有用并且可以正常工作。
问题出现在某些特定于平台的视图扩展上。我想以与平台无关的方式编写此代码,但不确定在某些特定情况下如何执行该代码。
首先,这是一个跨平台条件视图修饰符的工作示例。
import SwiftUI
struct DemoView: View {
var body: some View {
Text("Hello, demo!").padding()
.modifier(iosBackground())
}
}
struct iosBackground: ViewModifier {
#if os(OSX)
func body(content: Content) -> some View {
content
}
#else
func body(content: Content) -> some View {
content.background(Color.blue)
}
#endif
}
iosBackground
修饰符的作用是仅在iOS平台上应用视图修改(确切地说,在任何非OSX平台上,但在此示例中仅使用OSX和iOS) 。视图的OSX版本通过,而iOS版本返回修改后的视图。这个颜色示例当然是愚蠢且无用的,但是对于诸如填充之类的与布局相关的事情,这是一种非常实用的方法。
我的问题:我如何将相同的方法应用于诸如actionSheet之类的修饰符?这是我想做的事情:
struct DemoView: View {
@State var showActionSheet = true
var body: some View {
Text("Hello, demo!").padding()
.modifier(iosBackground())
.actionSheet(isPresented: $showActionSheet) {
ActionSheet(
title: Text("Actions"),
message: Text("Available actions"),
buttons: [
.cancel { },
.default(Text("Action")),
.destructive(Text("Delete"))
]
)
}
}
}
如果您尝试编译此代码,则在iOS上可以正常工作。在OSX上,它有一个编译错误,因为actionSheet
API在OSX上不可用。的确如此。我想这样做,以使actionSheet
调用在OSX上完全不起作用,但是我无法弄清楚如何构造和有条件地编译我的代码以使其实现。
问题再次出现:如何构造代码,以便在iOS上显示actionSheet,而在OSX上则是无操作?
答案 0 :(得分:1)
您快到了。如果您查看.actionSheet
的函数签名,就会找到解决方法。它返回不透明类型some View
,这是几乎所有SwiftUI视图的返回类型。因此,也请查看文档:
/// Presents an action sheet.
///
/// - Parameters:
/// - isPresented: A `Binding` to whether the action sheet should be
/// shown.
/// - content: A closure returning the `ActionSheet` to present.
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)
@available(OSX, unavailable)
public func actionSheet(isPresented: Binding<Bool>, content: () -> ActionSheet) -> some View
话虽如此,您可以像将.background
函数与内容一起使用一样使用它。因此,这是解决方案:
struct Sheet: ViewModifier {
@Binding var presented: Bool
func body(content: Content) -> some View {
#if os(OSX)
return content
#else
return content
.actionSheet(isPresented: $presented) {
ActionSheet(title: Text("Action Title"),
message: Text("Action Message"),
buttons: [.cancel(), .default(Text("Ok"))]
)
}
#endif
}
}
我刚刚将#if - #endif
移到了函数体内,这需要明确地使用return
关键字。您可以将其用作任何修饰符:
.modifier(Sheet(presented: $showActionSheet))