如何正确使用requestReview()请求应用评分
Hey there! Let's tackle your two key questions about App Store review prompts first, then dive into some tweaks for your code.
Question 1: Can I re-request a review if the user declined initially?
Absolutely! Here's the thing: Apple's SKStoreReviewController.requestReview() handles the heavy lifting of deciding when to actually show the prompt to the user. If a user taps "Later" or "No, Thanks", the system will automatically suppress any future prompts from your app for a period of time (usually weeks, depending on Apple's current rules).
You can keep triggering your own logic (like counting 3 more completed action sequences) and calling requestReview() when your conditions are met—just let Apple's system handle whether the prompt actually appears. You won't accidentally spam the user, since the system blocks repeated prompts after a decline.
Question 2: Can I call the review request from multiple app nodes, letting Apple control frequency?
This is not just allowed—it's actually a recommended practice! Since you can't guarantee users will hit your single pre-planned trigger point, adding the request call at multiple natural, positive interaction moments (like finishing a task, unlocking a feature, or completing a successful session) increases the chance that a user who's having a good experience will see the prompt.
Apple's system enforces a strict limit of 3 review prompts per user per 12-month period across all versions of your app. No matter how many times you call requestReview(), the system will only show the prompt if it's within that limit and the user hasn't declined recently. So feel free to add the call wherever it makes sense in your user flow—Apple will filter out any excess requests automatically.
Feedback on Your AppReviewRequest Code
First off, using @AppStorage to persist your run count and last version is a smart, clean approach. That said, there are a few small bugs and improvements to make:
Original Code
enum AppReviewRequest { @AppStorage("runCountSinceLastRequest") static var runCountSinceLastRequest = 0 @AppStorage("lastVersion") static var lastVersion = "" static let threshold = 4 static let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String static func countUpRequestReview() { if currentVersion != lastVersion { if runCountSinceLastRequest < threshold - 1 { runCountSinceLastRequest += 1 print(runCountSinceLastRequest) } } } static func requestReviewIfNeeded() { if currentVersion != lastVersion { if runCountSinceLastRequest == threshold { if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { SKStoreReviewController.requestReview(in: scene) lastVersion = currentVersion runCountSinceLastRequest = 0 } } } } }
Key Fixes & Improvements
Fix the Counting Logic Bug
Right now, yourcountUpRequestReview()stops incrementing whenrunCountSinceLastRequesthitsthreshold - 1(3, when threshold is 4). ButrequestReviewIfNeeded()only triggers when the count equalsthreshold(4)—so the prompt will never show up! Adjust the counting logic to increment until the threshold is reached:static func countUpRequestReview() { if currentVersion != lastVersion { runCountSinceLastRequest += 1 print(runCountSinceLastRequest) } }Then update the trigger condition in
requestReviewIfNeeded()to check if the count meets or exceeds the threshold:if runCountSinceLastRequest >= threshold { // Trigger review request }Avoid Force Unwrapping
The lineBundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! Stringuses force unwrapping, which could crash if the key is missing (unlikely, but better safe than sorry). Replace it with a safe optional binding:static let currentVersion: String = { guard let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String else { return "unknown" } return version }()Tweak Version Reset Logic
Your current logic resets the count and version only when the prompt is shown. That's fine, but if you want to ensure you don't count interactions from a previous version, you could reset the count immediately when a new version is detected (incountUpRequestReview()), but that's optional depending on your desired behavior.Trigger on Valuable Actions
Instead of callingcountUpRequestReview()on app launch, consider calling it only when the user completes your target action sequence. This ensures you're asking for a review after the user has a positive, intentional experience—boosting the chance they'll leave a rating.
内容的提问来源于stack exchange,提问作者Tom_Swift

