Is it possible determine if SKStore​Review​Controller has been presented.
Asked Answered
C

1

7

My intention is to either display the SKStore​Review​Controller (If applicable) or display my own feedback controller and redirect the user to the App Store. By doing this I can avoid asking the user for feedback more than once.

After reading Apple's lacking documentation on SKStore​Review​Controller (https://developer.apple.com/reference/storekit/skstorereviewcontroller) it seems that there is no way to determine if SKStore​Review​Controller is currently presented or has been presented previously.

I understand that I could potentially store the display frequency in NSUserDefaults, but I would prefer to avoid doing so.

Conciliatory answered 7/4, 2017 at 0:55 Comment(2)
You say that you don't want to use UserDefaults but even if there is a way to determine if SKStore​Review​Controller is currently presented or has been presented previously then how would you store the value then? But I would check this answer out.Earthworm
Possible duplicate of SKStoreReviewController how to detect that user has turned off Rate This App (RTA) in settings or 3 times limit has reached?Sellars
C
2

Here is how I detect if it has been presented.

private static func checkIfShownSKStoreReviewController(_ iteration: Int, originalWindowCount: Int) {
    let windows = UIApplication.shared.windows
    if windows.count > originalWindowCount {
        let window = windows[1]

        if window.className == "UITextEffectsWindow" || window.className == "UIRemoteKeyboardWindow" {
            print("Shown SKVC iteration: \(iteration)")

            //Do logic stuff like saving to your database
            return
        }
    }

    if iteration > 2000 {
        print("checkIfShownSKStoreReviewController: timeout, bailing \(iteration)")
        return
    }

    runThisAfterDelay(seconds: 0.02, after: {
        checkIfShownSKStoreReviewController(iteration + 1, originalWindowCount: originalWindowCount)
    })
}

private static func runThisAfterDelay(seconds seconds: Double, after: () -> ()) {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), after)
}

static func showReview() {
    print("Showing AppStore Review")
    if #available(iOS 10.3, *) {
        SKStoreReviewController.requestReview()
        checkIfShownSKStoreReviewController(0, originalWindowCount: UIApplication.shared.windows.count)
    }
}
Clamatorial answered 26/7, 2017 at 14:14 Comment(2)
Thanks for the answer. Although it will theoretically work, it's not exactly what I am looking for. It's not ideal to potentially wait 40 seconds then update the UI with an alternative feedback/review controller. Although in saying that, it's the best response I have seen thus far and it should eventually determine if the view has been displayed (Assuming it will be presented within the 40 seconds)Conciliatory
Well in my tries it usually presented in the 2-10th iteration. So 0.2 seconds max. But I'm sure it will vary by different factors. You could play with the iteration count and send a message after 5 seconds if you like.Clamatorial

© 2022 - 2024 — McMap. All rights reserved.