Swift Tutorial: Proper way to request review using SKStoreReviewController in iOS 10.3 and higher

One of the major targets of app developers is to get better exposure to the community and receive feedback from users to improve the apps and also encourage others to use their apps. For years, developers were using third party methods to suggest receiving review from users which mostly were based on how long and how often the user is engaged with their app. But one major issue in using those 3rd party methods was that the experience was not as seamless as you would expect. Usually, the user was sent out of the app to AppStore app to write the review where they even had to choose Review tab and then start writing the review. 

In iOS 10.3 update, Apple made several major changes in the iOS platform, in which one of the most favorable ones for developers is an official method for asking for review from users. From iOS 10.3, now we can ask StoreKit to ask user for their review and it would handle the rest of the work. You can see the documentations here. Theoretically, the developer only needs to add one line of code to request for review but there are couple notes to consider. 

Based on the documentations, the request review function uses a proprietary method to analyze if it is a suitable time to ask user for a review, therefore it is strongly recommended that developers avoid calling this function in response to a user action. For example, if you put request review in callback function for touching a button, iOS might decide not to show anything at the moment, so the user might think your app is not functioning well. On the other hand, it is important to consider not asking for user input very early, possibly wait for couple runs and then ask for review. Although we do not know what are Apple’s algorithms, but until we get to know how the method behaves, the best integration approach is to make sure we ask user at a proper time. 

Note: during development, all request for reviews would be accepted. meaning every single time, a request for review dialog would appear on screen but you are not able to submit the review. In Testflight, none of the requests will be approved, so do not panic if review dialog does not show up in your Testflight sessions. Once the app goes to production, it would use the Apple’s methods to show the dialog whenever it is suitable. 

Without further ado, here is how you can implement the request for review in Swift.

1. First, you need to import StoreKit

import StoreKit

2. Now you can ask for review by

SKStoreReviewController.requestReview()

That's it! Much easier as you might have imagined! 

Although if you would like to support older iOS versions it is better to do so like the following:

if #available(iOS 10.3, *) {
    SKStoreReviewController.requestReview()
           
} else {
    // Fallback on earlier versions
    // Try any other 3rd party or manual method here. 
}

Step by Step

Now my opinion on a proper way of implementing RequestReview :

1. Create a new Swift file in your project 

2. Import required frameworks

import Foundation
import StoreKit

3. Define setting variables 

let runIncrementerSetting = "numberOfRuns"  // UserDefauls dictionary key where we store number of runs
let minimumRunCount = 5                     // Minimum number of runs that we should have until we ask for review

4. Then create a manual run counter which simply stores number of runs in UserDefaults. To make the counter you need two functions. One to read from UserDefaults the other to increment by one and store in UserDefaults. 

func incrementAppRuns() {                   // counter for number of runs for the app. You can call this from App Delegate
    
    let usD = UserDefaults()
    let runs = getRunCounts() + 1
    usD.setValuesForKeys([runIncrementerSetting: runs])
    usD.synchronize()
    
}

func getRunCounts () -> Int {               // Reads number of runs from UserDefaults and returns it.
    
    let usD = UserDefaults()
    let savedRuns = usD.value(forKey: runIncrementerSetting)
    
    var runs = 0
    if (savedRuns != nil) {
        
        runs = savedRuns as! Int
    }
    
    print("Run Counts are \(runs)")
    return runs
    
}

5. The next would be a function to request for review. We have to consider two factors in this function. First, if we had enough number of runs to ask for review. Second, to check if we are running on iOS10.3 and higher so we can use the function. 

func showReview() {
    
    let runs = getRunCounts()
    print("Show Review")
    
    if (runs > minimumRunCount) {
        
        if #available(iOS 10.3, *) {
            print("Review Requested")
            SKStoreReviewController.requestReview()
            
        } else {
            // Fallback on earlier versions
        }
        
    } else {
        
        print("Runs are not enough to request review!")
        
    }
    
}

6. Next step is to call our run counter from App Delegate. So add the following in your App’s didFinishLaunchingWithOptions function

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        incrementAppRuns()
        return true
 }

7. The final step is to call showReview() in a proper time. I would suggest to call this function whenever user has accomplished a major work in the app. For example if you have a game, after you show results to the user you can call this function. Remember to call this function beside other jobs if you put it in a button callback. For example, in CMath, I put the showReview() function in back button of summary page. So when user have seen the results and tries to go to home page, the app takes the user to home page and if the requestReview method decides to show review, it will show the review dialog. This way we make sure our button always work properly, and also we show review request page when we are sure the user has done some major work in the app.  

showReview()

Voila! Now you can run your app and see the result. 

To make your job easier, you can download my script from Github which covers steps 1-5 of this tutorial. Click here to download the code

Don't forget to include your comments below. Happy coding!