skip to Main Content

There are some new environment variable I need to use, for example

@Environment(.requestReview) var requestReview // StoreKit

But my app needs to support older iOS. How do I "wrap" around this environment variable while not using iOS 16?

3

Answers


  1. We need to annotate view holding that, like

    @available(iOS 16, *)
    struct StoreKitView: View {
        @Environment(.requestReview) var requestReview
    
    // ...
    
    Login or Signup to reply.
  2. You can create your own extension for EnvironmentValues & in it do the check:

    extension EnvironmentValues {
        var requestReviewOld: SomeType? {
            get {
                if #available(iOS 16.0, *) {
                    self.requestReview
                }else {
                    nil
                }
            }
            set {
                if #available(iOS 16.0, *) {
                    self.requestReview = newValue
                }
            }
        }
    }
    
    Login or Signup to reply.
  3. I wish I could come up with a more idiomatic solution that would promote the usage of @Environment variables as the original API does, but declaring a new ViewModifier does the trick.

    Start by declaring a new ViewModifier, followed by its extension, to make it available on 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
            }
        }
    }
    

    You can then use it as follows:

    @State private var canRequestReview = false
        
    var body: some View {
        ContentView()
            .requestReview($canRequestReview)
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search