在支持旧版iOS的情况下,如何使用iOS 16环境变量?

6

有一些新的环境变量我需要使用,例如

@Environment(\.requestReview) var requestReview // StoreKit

但是我的应用程序需要支持旧版iOS。我该如何在不使用iOS 16的情况下“包装”这个环境变量?

4个回答

2

您可以为EnvironmentValues创建自己的扩展,并在其中进行检查:

extension EnvironmentValues {
    var requestReviewOld: SomeType? {
        get {
            if #available(iOS 16.0, *) {
                self.requestReview
            }else {
                nil
            }
        }
        set {
            if #available(iOS 16.0, *) {
                self.requestReview = newValue
            }
        }
    }
}

这对于动态变化的环境属性,比如isLuminanceReduced,是行不通的,对吗? - Tomáš Kafka
我不明白为什么它不能。你试过了吗? - Timmy

2

我希望能够想出一种更习惯用语的解决方案,以促进像原始API一样使用@Environment变量,但声明一个新的ViewModifier就可以解决问题。

首先声明一个新的ViewModifier,然后跟随其扩展,使其在View上可用:

@available(iOS 16, *)
struct StoreReviewModifier: ViewModifier {
    @Binding var canRequestReview: Bool

    @Environment(\.requestReview) var requestReview

    func body(content: Content) -> some View {
        content
            .onChange(of: canRequestReview) { newValue in
                if newValue {
                    requestReview.callAsFunction()
                }
            }
    }
}

public extension View {
    @ViewBuilder func requestReview(_ canRequestReview: Binding<Bool>) -> some View {
        if #available(iOS 16, *) {
            modifier(StoreReviewModifier(canRequestReview: canRequestReview))
        } else {
            self
        }
    }
}

然后您可以按照以下方式使用它:

@State private var canRequestReview = false
    
var body: some View {
    ContentView()
        .requestReview($canRequestReview)
    }
}

如何在iOS 15上添加请求评论的支持? - Idan

1
我们需要注释视图持有,就像这样。
@available(iOS 16, *)
struct StoreKitView: View {
    @Environment(\.requestReview) var requestReview

// ...

4
但是你只能在iOS 16中使用该视图。这不是一个理想的解决方案。 - Mikrasya

1
环境是一个全局变量,因此可以通过以下方式获取:
@available(iOS 17.0, *)
struct WidgetMarginsProvider: View
{
    @Environment(\.widgetContentMargins) var margins
    
    var body: some View {
        Color.clear
    }
}

extension View
{
    var widgetContentMargins: EdgeInsets {
        if #available(iOS 17.0, *)
        {
            return WidgetMarginsProvider().margins
        }
        else
        {
            return EdgeInsets(16, 16, 16, 16)
        }
    }
}

struct ExampleView: View
{
    var body: some View {
        Text("Hello")
            .padding(widgetContentMargins)
    }
}

更新,所以上述解决方案不起作用,因为@Environment只在视图块中起作用。
新的解决方案:
查看此链接:https://developer.apple.com/forums/thread/733780

你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人能够确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Community
虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案如果链接页面发生变化,就会失效。- 来自评论 - soundflix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接