我正在尝试为框架创建可重用的SwiftUI View
,然后可以在iOS / iPadOS和macOS上使用它。
这通常可以正常工作;但是,由于macOS视图没有导航栏,因此当视图包含在macOS目标中时,包括导航栏标题(对于iOS而言很重要)会导致错误:
.navigationBarTitle(Text("Page Title"))
类型'...'的值没有成员'navigationBarTitle'
关于条件编译(或任何其他)方法的任何建议都可以为两个平台构建相同的视图?
我来的最接近的是以下。包括额外的Text
视图很容易,但是由于栏标题是修饰符,因此在条件编译中仅包装该部分会产生其他错误:
public struct ExampleView: View {
private let pageTitle = "Page Title"
public var body: some View {
VStack(alignment: .center) {
#if os(macOS)
Text(pageTitle)
.font(.title)
#endif
Spacer()
Text("This is the view content")
Spacer()
}
#if !os(macOS)
.navigationBarTitle(Text(pageTitle))
#endif
}
}
意外的平台状况(预期的“ os”,“ arch”或“ swift”)
函数声明了一个不透明的返回类型,但是在其主体中没有用于从其推断基础类型的返回语句
答案 0 :(得分:1)
您可以向View结构添加扩展名。它将条件编译放在块外,并按您期望的那样工作
#if os(macOS)
extension View {
func navigationBarTitle(_ title: Text) -> some View {
return self
}
}
#endif
答案 1 :(得分:0)
我建立了一种方法:将主要内容移动到另一个View
属性,然后对其进行修改以添加导航栏标题(如果需要),然后将其返回为body
。当以这种方式分开时,可以使用条件编译。
这有点不雅致,但可以。它也可以用于设置特定于macOS的内容,例如视图的整体框架大小。欢迎提出更好的方法的建议!
Swift v5.1
public struct ExampleView: View {
private let pageTitle = "Page Title"
#if !os(macOS)
public var body: some View {
main.navigationBarTitle(Text(pageTitle))
}
#else
public var body: some View {
main.frame(
minWidth: 500,
minHeight: 500
)
}
#endif
public var main: some View {
VStack(alignment: .center) {
#if os(macOS)
Text(pageTitle)
.font(.title)
#endif
Spacer()
Text("This is the view content")
Spacer()
}
}
}