Pattern · Settings
NewNotification Settings SwiftUI Block
The Notifications page of Settings: the real iOS permission, Push, Email and SMS per category, quiet hours and a digest that autosave.
Where people choose what reaches them and how. A status card reads the app's real permission and offers Turn on notifications or Open Settings, each category toggles its Push, Email and SMS chips, and quiet hours and the email digest sit beside them. Every change writes through your binding and saves after a short pause, with Saving, Saved and Not saved with Retry shown beside the group you changed.
- SwiftUI
- iOS 17.0+
- notification-settings
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- Reads the real notification permission and asks or opens Settings from it
- Push, Email and SMS chips for each kind of notification
- Quiet hours with From and To times, and an Off, Daily or Weekly digest
- Autosaves after a pause, with Saving, Saved and Retry beside each group
- Loading, never asked, declined and quiet delivery states
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
A status card at the top reads the app's authorization from UNUserNotificationCenter and reads it again whenever the app comes back to the foreground. Allowed shows an "Allowed" chip and a "Banners, sounds and badges" row that opens the app's notification page in iOS Settings. Never asked shows "Notifications are off" with Turn on notifications, which asks iOS and shows a spinner until the person answers. Declined shows "Turned off in Settings" with Open Settings, and provisional delivery shows "Delivered quietly" with the same Turn on button. Under it, the Categories card lists each kind of notification with its symbol, title and a line on what it covers, and a chip for each channel it offers: Push, Email and SMS turn on and off with a tap and show a checkmark when on. Push chips dim while iOS has notifications off. Quiet hours is a switch that reveals From and To time rows. Email digest is a segmented Off, Daily or Weekly control with a line on what each sends. Every change writes through your binding at once; after a short pause the block runs your onSave and the card you changed shows "Saving…", then "Saved" beside its title. A thrown error shows "Not saved" with Retry beside the title and the message under the card. Pass nil while the preferences load and the block shows grey shapes in its own layout.
Notes
NotificationSettings(preferences:authorization:onSave:)takes aBinding<NotificationSettings.Preferences?>and anasync throwssave closure. It is a section: no navigation stack, background, padding or scroll view of its own, so place it in your own column, such as aScrollViewwith.padding(.horizontal, 20).Preferencesholds thecategories, thequietHoursand thedigest.Preferences.sampleis Messages (Push and Email on), Reminders (Push on) and Product news (Push and Email offered, both off), quiet hours off and a weekly digest.- A
Categoryhas a stableidfor saving, atitle, an optionaldetailline and SF Symbol, theavailablechannels in display order (all three by default) and thechannelsthat are on. Offer only the channels your backend can send. Channelis.push,.emailor.sms.QuietHoursisisOnwithfromandtoasTime(hour and minute in the person's calendar), 22:00 to 7:00 by default.Digestis.off,.dailyor.weekly.onSavereceives the wholePreferencesabout 0.6 seconds after the last change, so a run of taps sends one request. A new change cancels a save that hasn't started. Throw to fail: the block shows aLocalizedError'serrorDescription, or "Your changes weren't saved. Check your connection and try again." Retry sends the current preferences again. The binding keeps the person's choices either way.authorizationoverrides what the card shows (.allowed,.quiet,.denied,.notDetermined), for previews or an app that tracks permission itself. Leave it nil and the block reads the system.- Turn on notifications calls
requestAuthorization(options: [.alert, .sound, .badge]). Register for remote notifications in your own app delegate as usual; the block only reads and requests authorization. Open Settings and the Allowed row useUIApplication.openNotificationSettingsURLString. - Haptics: a selection tick on each chip, switch and digest change, success when a save lands and an error when one fails.
- VoiceOver reads each category with the channels that are on ("Messages, Push and Email"), each chip as a toggle with On or Off, the digest as a selected tab, and announces "Saved", a failed save's message and the answer to the permission request. Every target is at least 44 points tall. At accessibility sizes the chips move under the title and stack when they no longer fit in a row.
- Reduce Motion turns the chips, the quiet hours rows and the save status into short fades.
NotificationSettingsExampleat the end ofNotificationSettings.swiftis the Notifications page from the preview: the sample preferences in a scroll view with a save that takes a moment and succeeds. It reads the system authorization, so a first run offers Turn on notifications. PasswrapsInNavigationStack: falseto push it in your own stack. The States preview shows the never-asked card with a save that fails, the declined card and the loading layout.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - Cards are
color.surfacewithradius.lg; rows are 16 points in from the edge (space.lg) withSPHairlinedividers inseparator, inset to the text. Groups sit 24 points apart (space.xl) undertype.headlinetitles intextPrimary. - Titles are
type.bodyintextPrimary, detail linestype.footnoteintextSecondary, symbolstextSecondary, the Allowed row's arrowtextTertiary. The save status istype.footnote: "Saving…" intextTertiary, "Saved" with a checkmark intextSecondary, "Not saved" and the error indanger, Retry semibold intextPrimary. - Channel chips are capsules in
type.subhead: on istextPrimarywith a checkmark onfillinside a fainttextPrimaryhairline, off istextSecondaryinside aseparatorhairline. They are 32 points tall inside a 44 point target. The digest control is afilltrack with asurfaceElevatedthumb. - The Allowed chip is
successon a tint of it. Turn on notifications and Open Settings areaccentwithaccentOntext intype.headline,radius.md, the block's primary action. The quiet hours switch isaccentwith anaccentOnthumb when on andfillwith a white thumb when off. - Changes move with
motion.snappyand the loaded layout fades in withmotion.smooth; both become short fades under Reduce Motion.
03
Keep building
Pieces that work well next to this one.