如何使用仅适用于 iOS 14+ 且部署目标为 iOS 13 的视图修饰符

Jor*_*n H 10 ios swiftui ios14

当视图仅在 iOS 14 上可用但您的应用可用于 iOS 13 时,如何向视图添加视图修饰符?

例如,textCase(_)。iOS 14 中的部分标题是大写的,因此要使用您应该.textCase(.none)在 上设置的标题文本的大小写Text,但这直到 iOS 14 才存在。

Section(header:
    Text("Header")
        .textCase(.none) //FIXME: 'textCase' is only available in iOS 14.0 or newer
        .font(.system(size: 14, weight: .bold))
        .foregroundColor(.secondary)
        .padding(.top, 50)
)
Run Code Online (Sandbox Code Playgroud)

Xcode 提供了一些建议:

  • 添加 if #available 版本检查
  • 添加@available 属性

如果您使用#available 版本检查,它会用#available 包装所有范围内的代码,因此您必须复制所有这些以添加那一行代码。如果使用 @available,则必须复制整个 body 属性或整个结构。

我考虑创建我自己的 ViewModifier ,它只会在 iOS 14 时应用它,但这会产生这个可怕的错误:

函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型

struct CompatibleTextCaseModifier: ViewModifier {
    func body(content: Content) -> some View {
        if #available(iOS 14.0, *) {
            return content
                .textCase(.none)
        } else {
            return content
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 10

标记body@ViewBuilder- 这将允许自动跟踪内部不同的返回类型,并删除return因为显式返回禁用视图构建器包装器。

所以这里是固定变体

struct CompatibleTextCaseModifier: ViewModifier {

    @ViewBuilder
    func body(content: Content) -> some View {
        if #available(iOS 14.0, *) {
            content
                .textCase(.none)
        } else {
            content
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和用法

Section(header:
    Text("Header")
        .modifier(CompatibleTextCaseModifier())
        .font(.system(size: 14, weight: .bold))
        .foregroundColor(.secondary)
        .padding(.top, 50)
) {
    Text("test")
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案非常适合像这样的简单情况,但如果你有一个大项目,有数十或数百个仅在 iOS 14 中可用的视图修饰符,那么为每个案例创建兼容的修饰符将是令人畏惧的,并且你会发送奇怪的消息视图修饰符名称,我为此创建了一个新问题:/sf/ask/4822449971/ Between- Different-ios-versions-without-available (3认同)