Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

requestReview()' was deprecated in iOS 14.0

I'm using StoreKit to ask review automatically in my app.

func requestReview() {
    guard shouldRequestReview else {return}
    SKStoreReviewController.requestReview()
    lastRequest = Date()

How to get rid of that warning?

@ Dc7 - In your code it looks like you are logging the dates when you last showed the request review, would you mind sharing your logic? I have an app in the AppStore and some users report that they keep getting the RateApp request and I'm wondering if I'm doing something wrong. After 10 launches, I ask the user to rate the app but I only call the SKStoreReviewController.requestReview() method, no other logic and I don't log any dates. Would you mind sharing your logic before calling the SKStoreReviewController.requestReview() method? – fs_tigre Dec 21, 2022 at 1:31

iOS 16+

There is now a new RequestReviewAction that is available as an environment value:

private struct ContentView: View {
    @Environment(\.requestReview) private var requestReview
    var body: some View {
        Button("Review") {
            DispatchQueue.main.async {
                requestReview()

iOS 14+

Quick solution

if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
    DispatchQueue.main.async {
        SKStoreReviewController.requestReview(in: scene)

Note: according to some comments it's more reliable with DispatchQueue.main.async

Convenient solution

Here's a true one-liner:

SKStoreReviewController.requestReviewInCurrentScene()

but first you need to create the following extension in SKStoreReviewController:

extension SKStoreReviewController {
    public static func requestReviewInCurrentScene() {
        if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
            DispatchQueue.main.async {
                requestReview(in: scene)

Here is a GitHub repository with different Swift extensions including requestReviewInCurrentScene().

Explanation

The requestReview function was deprecated in iOS 14:

@available(iOS, introduced: 10.3, deprecated: 14.0)
open class func requestReview()

You need to use the requestReview(in:) function instead:

@available(iOS 14.0, *)
open class func requestReview(in windowScene: UIWindowScene)

Possible solutions

  • Custom extension
  • You can create the following extension:

    extension UIApplication {
        var currentScene: UIWindowScene? {
            connectedScenes
                .first { $0.activationState == .foregroundActive } as? UIWindowScene
    

    and use it like this:

    if let scene = UIApplication.shared.currentScene {
        SKStoreReviewController.requestReview(in: scene)
    
  • Universal one-liner:
  • if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
        SKStoreReviewController.requestReview(in: scene)
    
  • single scene solution (for iOS)
  • if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
        SKStoreReviewController.requestReview(in: scene)
                    This is NOT ideal solution on iPad IMO. When you have multiple WindowScenes opened, the review popup shows up in first connectedScene even the window is in background.
    – toshi0383
                    Sep 22, 2020 at 6:41
                    @toshi0383 Yes, you're right. When I was answering this I thought about iOS only. Please see the updated answer for multiple scenes.
    – pawello2222
                    Sep 22, 2020 at 7:14
                    @pawello2222 , do you know the answer of this question? stackoverflow.com/questions/69272521/…
    – RRN
                    Sep 21, 2021 at 16:39
                    What would the equivalent solution for macOS? The great thing about the old function was that it was OS-agnostic.
    – TheNeil
                    Dec 14, 2021 at 17:30
    

    iOS (Swift 5+):

        if #available(iOS 14.0, *) {
            if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
                SKStoreReviewController.requestReview(in: scene)
        } else if #available(iOS 10.3, *) {
            SKStoreReviewController.requestReview()
    

    macOS: Don't forget to replace your Apple ID with in URL "id123456789"

    guard let writeReviewURL = URL(string: "https://itunes.apple.com/app/id123456789?action=write-review") else {
          print("Invalid URL")
          return
    NSWorkspace.shared.open(writeReviewURL)
                    What would the equivalent solution for macOS? The great thing about the old function was that it was OS-agnostic.
    – TheNeil
                    Dec 14, 2021 at 17:30
    

    I made a small wrapper over SKStoreReviewController that saves the headache of supporting different versions of ios. Also it works for macOS.

    // Review after 3 launches
    AppReview.requestIf(launches: 3)
    // Review after 5 days
    AppReview.requestIf(days: 5)
    // Review after 3 launches and 5 days
    AppReview.requestIf(launches: 3, days: 5)
    

    https://github.com/mezhevikin/AppReview

    iOS 16 has a new way to do it: https://developer.apple.com/documentation/storekit/requestreviewaction

    In my tests it is crucial to do it on the main queue. Otherwise the dialogue is unreliable.

    private struct ContentView: View {
        @Environment(\.requestReview) private var requestReview
        var body: some View {
            Button("Ask for Review") {
                DispatchQueue.main.async {
                    requestReview()
    

    As SKStoreReviewController.requestReview is deprecated in ios14 You can use SKStoreReviewController.requestReview(in: scene) from ios14
    Sample code is below

    if #available(iOS 14.0, *) {
        if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
            SKStoreReviewController.requestReview(in: scene)
    } else if #available(iOS 10.3, *) {
        SKStoreReviewController.requestReview()
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.