Engineering
Permission prompts are one of the few moments where iOS puts a system-level interruption directly between your app and the user, in language you write. Getting the timing and the explanation right measurably affects acceptance rates — and getting the mechanics wrong can mean a permission you genuinely need gets declined and then becomes very hard to recover.
Every permission that requires a system prompt on iOS also requires a matching "usage description" string in your Info.plist, written by you, explaining specifically why your app needs it. Apple's App Review checks that these strings are present, specific, and consistent with what the app actually does — a generic string like "this app needs your location" for a feature that clearly requires precise, continuous tracking is the kind of mismatch that draws review scrutiny.
Requesting every permission your app might ever need during the first launch is a common and avoidable mistake. A priming screen explaining why you're about to ask, shown immediately before the system dialog and tied to the specific feature the user just tried to use, converts meaningfully better than a wall of unexplained system prompts on first open.
Once a user declines a system permission prompt, you cannot simply show it again — iOS won't re-trigger the native dialog. The only path back is deep-linking the user to your app's page in the Settings app (via UIApplication.openSettingsURLString), which most users never follow through on. Design a real, graceful degraded state for a declined permission rather than a dead end — a feature that's unavailable but explained, not a screen that just stops working.
Android groups permissions into "dangerous" categories requested individually at runtime, similar in spirit to iOS. The shouldShowRequestPermissionRationale API lets you detect when a user has previously declined and show your own explanation before asking again, which iOS doesn't offer directly. Scoped storage, introduced in Android 10, limits broad file-system access to app-specific directories by default, and POST_NOTIFICATIONS became its own explicit runtime permission starting in Android 13, rather than being granted automatically the way notifications previously were.
Most teams thoroughly test what happens when a user grants a permission and rarely test what happens when they don't — and yet decline is a completely normal, expected outcome that App Review itself will exercise. Before submitting, walk through every permission-gated feature in your app with each permission explicitly denied, and confirm the app degrades gracefully rather than silently failing or crashing. A reviewer who declines a permission and hits a broken screen will treat that as a completeness bug (guideline 2.1), not a permissions edge case.
A handful of permissions carry extra review scrutiny beyond the standard usage-string requirement. Background location, Critical Alerts, and NFC-related entitlements all require additional justification in your App Review notes explaining specifically why the standard, more limited alternative isn't sufficient — Apple wants to see that you've considered the narrower option first, not just defaulted to the broadest permission available because it was easier to implement.
It's worth remembering, too, that a granted permission isn't permanent consent to use it however you like — both platforms expect the data accessed through a permission to be used only for the purpose described in your usage string, and that expectation is enforced through App Review's ongoing scrutiny of app behavior, not just at the moment of the first prompt.
Treat every permission request as something the user has to actively decide to trust you with, not a formality to get through as fast as possible — the apps that ask well tend to get granted access more often, and lose less goodwill when they don't.
More from the journal
App Store
Apple rejects a meaningful share of first-time submissions, and it's rarely the exotic reasons founders worry about. Here's what actually trips people up, and how to submit clean.
Launch
Launch day is the easy part. The work that determines whether it goes well happens weeks earlier — here's the sequence we actually follow.
Engineering
Cross-platform frameworks have closed most of the historical gap with native — but not all of it. Here's the actual decision framework, not a philosophy war.