87

In iOS 14, Xcode is showing a warning:

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()
}

enter image description here

How to get rid of that warning?

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
Dc7
  • 1,405
  • 1
  • 10
  • 16
  • @ 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 '22 at 01:31

5 Answers5

185

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)
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • 1
    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 '20 at 06:41
  • 4
    @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 '20 at 07:14
  • @pawello2222 , do you know the answer of this question? https://stackoverflow.com/questions/69272521/requestreview-doesnt-work-if-i-open-my-app-manually – RRN Sep 21 '21 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 '21 at 17:30
  • 1
    i would add DispatchQueue.main.async { } to requestReviewInCurrentScene()'s body – Jean Raymond Daher Aug 31 '22 at 15:11
59

Simple solution for iOS(13 & above) and macOS

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)
Ashvin
  • 8,227
  • 3
  • 36
  • 53
  • What would the equivalent solution for macOS? The great thing about the old function was that it was OS-agnostic. – TheNeil Dec 14 '21 at 17:30
3

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

user2168735
  • 395
  • 4
  • 14
0

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()
            }
        }
    }
}
Nico S.
  • 3,056
  • 1
  • 30
  • 64
-8

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()
}
Jagveer Singh
  • 2,258
  • 19
  • 34