Pattern · Settings
NewPrivacy Settings SwiftUI Block
The Privacy page of Settings: each permission's real status with a tap to ask or change it, data toggles, a data export and the policies.
Where people see what the app may use and what it does with their data. Each permission you declare shows its real status from iOS, asks there and then when it was never asked, and opens Settings otherwise. Data toggles, Download my data with working, done and failed states, blocked accounts and the policies follow.
- SwiftUI
- iOS 17.0+
- privacy-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.
- Camera, Photos, Location, Contacts, Microphone and Notifications read live from iOS
- Allowed, Limited, Not allowed and Not asked chips, with Limited for partial access
- Tapping Not asked asks iOS in place; any other status opens Settings
- Data toggles bound to your settings and Download my data with its states
- Blocked accounts, Privacy policy and Terms rows appear when you pass them
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
The Permissions card lists the permissions you pass, each with its symbol, name, the reason you give and a status chip read from iOS: Allowed, Limited (selected photos, approximate location, chosen contacts, quiet notifications), Not allowed or Not asked. Statuses are read again whenever the app comes back to the foreground. Tapping a permission that was never asked asks iOS there and then: the chip turns to a spinner while the system alert is up and shows the answer when it closes. Tapping any other opens the app's page in iOS Settings, where the person changes it, and a footnote under the card says so. Your data holds Personalized recommendations and Share analytics as switches bound to your choices. Under it, Download my data which runs your request with a spinner, then a checkmark and "Requested. You'll get an email with a link.", or the error in the danger colour. Blocked accounts shows its count and opens your list, and Privacy policy and Terms of service open in the browser. Every row and group appears only when you pass what it needs.
Notes
PrivacySettings(permissions:choices:statuses:blockedCount:privacyPolicy:terms:onDownloadData:onBlockedAccounts:). Onlypermissionsandchoicesare required. 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).permissionsis a list ofPrivacySettings.Permissionin display order:.camera(_:),.photos(_:),.location(_:),.contacts(_:),.microphone(_:)and.notifications(_:), each with an optional reason ("Scan receipts and documents."). Pass only the ones your app uses. An empty list hides the Permissions card.Permission.samplesis Camera, Photos, Location and Notifications from the preview.- Status comes from the system:
AVCaptureDevicefor camera and microphone,PHPhotoLibraryat the read and write level,CLLocationManager(reduced accuracy reads as Limited),CNContactStoreandUNUserNotificationCenter(provisional reads as Limited). Location asks for When In Use. Passstatuses([Permission.Kind: Status]) to show your own values instead, for previews or an app that tracks them; tapping Not asked still asks iOS. Statusis.allowed,.limited,.denied(declined or restricted) or.notAsked.choicesis aBinding<PrivacySettings.Choices>withpersonalizedRecommendationsandshareAnalytics, both on by default. Save them where you save other settings; the switches only write the binding.onDownloadDataisasync throws: ask your backend to prepare an export there. The button shows a spinner, then a checkmark and stays done. Throw to fail: the block shows aLocalizedError'serrorDescription, or "The request didn't go through. Try again.", and the button can be tapped again. Nil hides Download my data.onBlockedAccountsopens your blocked accounts list;blockedCountshows beside it.privacyPolicyandtermsare URLs that open with the environment'sopenURL. Each nil hides its row, and the card goes when all three are nil.- Haptics: a selection tick on each switch, success when a data request lands and an error when it fails.
- VoiceOver reads each permission as one element with its reason and status ("Camera, Scan receipts and documents., Allowed"), with a hint for what a tap does, and announces the answer after asking and the result of a data request. Switches are native toggles through
accessibilityRepresentation. Rows are at least 52 points tall. At accessibility sizes the chip moves under the permission's name. - Reduce Motion turns status changes and the button states into short fades.
PrivacySettingsExampleat the end ofPrivacySettings.swiftis the Privacy page from the preview: the sample permissions read live from the system, both data toggles on, three blocked accounts, both policies and a data request that takes a moment and succeeds. PasswrapsInNavigationStack: falseto push it in your own stack. The States preview fixes every status and shows a data request that fails.
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; the footnote under Permissions istype.footnoteintextSecondary. - Titles are
type.bodyintextPrimary, reasonstype.footnoteintextSecondary, symbolstextSecondary, chevrons and the open arrowtextTertiary. - Chips are
type.footnotemedium: Allowed insuccessand Limited inwarning, each on a 14% tint of itself; Not allowedtextSecondaryonfill; Not askedtextPrimaryinside aseparatorhairline. - Download my data is a secondary button:
fillwithtextPrimaryintype.headline,radius.md, 52 points. Its note istype.footnoteintextSecondary, ordangeron a failure. - Switches are
accentwith anaccentOnthumb when on andfillwith a white thumb when off; they are the block's only accent. - Changes move with
motion.snappyand become short fades under Reduce Motion.
Requirements
- An Info.plist usage description for each permission you pass, or iOS ends the app when the block asks:
NSCameraUsageDescription,NSPhotoLibraryUsageDescription,NSLocationWhenInUseUsageDescription,NSContactsUsageDescription,NSMicrophoneUsageDescription. Notifications need no key.
03
Keep building
Pieces that work well next to this one.