Pattern · Sheets and Alerts
NewPermission Primer SwiftUI Block
Explain-then-ask for notifications, location, the camera or photos, then answer what iOS says: granted, or Open Settings.
A primer shown before a system permission prompt. It explains why the app needs the permission, lists what it makes possible, draws the alert iOS will show next, then requests the real permission. Granted turns to a check and calls back; denied explains where to change it and offers Open Settings, and turns granted when the person comes back having allowed it.
- SwiftUI
- iOS 17.0+
- permission-primer
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- One large symbol, the reason and two or three benefits
- A drawing of the alert iOS shows next, so the prompt is no surprise
- Continue requests the real permission for notifications, location, camera or photos
- Granted shows a check and calls onGranted; denied offers Open Settings
- Reads the current status on appear and again on return from Settings
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
One large SF Symbol (not in a tile), a title in the display face and the reason in a sentence, then a card of two or three things the permission makes possible, each with a symbol, a short title and a line. Under it, a small drawing of the alert iOS will show next, with its title, message and buttons, so the system prompt is no surprise. Continue requests the real permission: notifications through UNUserNotificationCenter, location through CLLocationManager, the camera through AVCaptureDevice and photos through PHPhotoLibrary. It shows progress while the system alert is up. Granted shows a check on Continue, then the symbol turns into a check in the success colour, the words change ("Notifications are on") and onGranted runs. Denied changes the symbol to its off form, says where to turn it on, and offers Open Settings; when the person comes back having turned it on, the block turns granted by itself. Not now leaves without asking, so the system's one prompt is kept for a better moment. The block reads the current status as it appears, so a permission already granted or denied opens on that state.
Notes
PermissionPrimer(kind:content:onGranted:onNotNow:request:)takes aKind(.notifications,.location,.camera,.photos) and everything else is optional.- It is a section: no scroll view, background or padding of its own. Use it inline in a screen's column, or as a sheet's content in a
ScrollViewwith 20 point margins. PermissionPrimer.Contentholds the symbol, title, reason,benefits(each aBenefitwithsymbol,titleanddetail), the Continue title, the sample alert's title, message and button labels, and the granted and denied titles and lines.Content.standard(for:appName:)gives plain defaults for each kind, naming your app fromCFBundleDisplayNameand reading the sample alert's message from your purpose string. Start from it and change what you need.Content.sampleis the notifications primer from the preview.onGranted(Status)runs about a second after the permission is granted, with.grantedor, for photos,.limited; dismiss the sheet or move on there. Granted also shows Done, which calls it again, for inline use.onNotNowdefaults to dismissing the presenting sheet.requestreplaces the system request, for example to ask for provisional notifications or go through your own permission service. Return aStatus(.notDetermined,.granted,.limited,.denied). With it set, the block doesn't read the current status on appear. A thrownLocalizedErrorshows its message under Continue.- Notifications ask for alerts, badges and sounds. Location asks for when-in-use; the block keeps its
CLLocationManageralive until the answer comes. Photos ask for read and write access. - Open Settings opens
UIApplication.openSettingsURLStringwithopenURL. - Haptics: success on granted, a warning on denied.
- VoiceOver reads the sample alert as one line ("Next, iOS asks: ..."), each benefit as one element, announces the result, and reads Continue as "Waiting for your answer" while the system alert is up. Text grows with Dynamic Type; the symbol and the sample alert stop growing at large sizes so the words keep the room.
- Reduce Motion turns the symbol change and state changes into short fades.
PermissionPrimerExampleat the end ofPermissionPrimer.swiftis a Reminders screen that primes notifications in a sheet as it opens and reads On once allowed. PasswrapsInNavigationStack: falseto push it in your own stack.- The real system alert can't be shown in a preview. The web preview's alert is a stand-in for it.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - The title is the one display moment:
type.faceat 28 points,type.displayWeightcapped at semibold, intextPrimary, falling back totype.textDesignwhen figures are monospaced. The reason istype.subheadintextSecondary. - The symbol is 52 points regular in
textPrimary,successwhen granted andtextSecondarywhen denied. - The benefits card is
color.surfaceatradius.lgwithseparatorhairlines inset to the text; its symbols aretextSecondary, titlestype.subheadsemibold, linestype.footnote. - The sample alert is
surfaceElevatedwith aseparatorstroke,type.footnoteandtype.caption. - Continue (then Done or Open Settings) is the only accent:
accentwithaccentOnintype.headlineatradius.md. Not now is a plaintextPrimarybutton. Errors aredanger. - Groups sit 24 points apart (
space.xl); changes usemotion.smoothandmotion.snappy.
Requirements
- The purpose string for the kind you ask for:
NSLocationWhenInUseUsageDescription,NSCameraUsageDescriptionorNSPhotoLibraryUsageDescription. Notifications need no key.
03
Keep building
Pieces that work well next to this one.