有一些新的环境变量我需要使用,例如
@Environment(\.requestReview) var requestReview // StoreKit
但是我的应用程序需要支持旧版iOS。我该如何在不使用iOS 16的情况下“包装”这个环境变量?
您可以为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
}
}
}
}
我希望能够想出一种更习惯用语的解决方案,以促进像原始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)
}
}
@available(iOS 16, *)
struct StoreKitView: View {
@Environment(\.requestReview) var requestReview
// ...
@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)
}
}
isLuminanceReduced
,是行不通的,对吗? - Tomáš Kafka