PermissionsKit is a Swift package that gives apps one universal API for requesting system permissions and reading their status — .authorized, .denied, .notDetermined — aimed at Apple-platform developers who want to link only the permission products their app actually uses.
What it is
PermissionsKit is a Swift package distributed through Swift Package Manager in Xcode, and it lives in the Apple/iOS ecosystem. It provides a single call surface for the permissions an iOS app can request from the user, covering sixteen of them: Bluetooth, Calendar, Camera, Contacts, FaceID, Health, Location, Media Library, Microphone, Motion, Notification, Photo Library, Reminders, Siri, Speech Recognizer and Tracking. Every permission ships as its own product, such as CameraPermission, LocationPermission or NotificationPermission, and the app compiles only the products it links.
The problem it replaces is hand-written permission handling spread across an iOS codebase. Each Apple framework has its own request pattern, its own status representation and its own required Info.plist usage description key, so teams end up duplicating that logic per framework and per feature. PermissionsKit collapses it to one shape: request with Permission.notification([.alert, .badge, .sound]).request { }, read state with Permission.camera.authorized, and look up the required plist key with Permission.bluetooth.usageDescriptionKey. The closure runs once the user answers the system dialog, so call sites stay in one place.
Key capabilities
- One request API across all permissions, with the completion closure called after the user answers the system dialog.
- Tri-state status reading:
.authorized, .denied and .notDetermined.
- Sixteen separately linkable products, including
BluetoothPermission, CalendarPermission, CameraPermission, ContactsPermission, FaceIDPermission, HealthPermission, LocationPermission, MediaLibraryPermission, MicrophonePermission, MotionPermission, NotificationPermission, PhotoLibraryPermission, RemindersPermission, SiriPermission, SpeechRecognizerPermission and TrackingPermission.
- Plist key lookup through
usageDescriptionKey, which returns the key itself (NSCameraUsageDescription) rather than the description text.
- Multi-key coverage where Apple requires it, such as
NSLocationAlwaysAndWhenInUseUsageDescription with NSLocationWhenInUseUsageDescription, and the three Calendar access keys.
- Localisation support: an xliff export creates the keys automatically, or they can be written by hand in
InfoPlist.strings as "NSCameraUsageDescription" = "Here description of usage camera";.
- Documented exception: Notification has no
Info.plist key. FaceID cannot distinguish .authorized from .notDetermined — both return .notDetermined, and only .denied is reliable.
Who uses it and how
- iOS teams shipping through App Review, because linking only the permission products in use keeps unused permission APIs out of the binary and avoids review questions about why the app declares them.
- Apps with onboarding flows that ask for several permissions in sequence, such as camera, photo library and notification, using the same request shape for each.
- Localisation workflows that run an xliff export to generate the
InfoPlist.strings keys instead of adding the file and writing keys by hand.
- Read-only status checks that gate UI, for example reading
Permission.camera.authorized before presenting a capture screen.
- Projects already on Swift Package Manager inside Xcode, which is the only install path documented.
Getting started
In Xcode, use File → Add Package Dependencies, paste https://github.com/sparrowcode/PermissionsKit, then select the permission products the app needs. Import PermissionsKit plus the product modules, for example import PermissionsKit and import NotificationPermission.
How it compares
The facts name no comparable tools and no list of paid products that this project replaces, so no such contrast can be drawn here. PermissionsKit stands alone in this registry on that basis. Readers looking for a comparison against a commercial or competing package will not find one in these facts.
When to use it — and when not to
It is a client-side library, so a self-hoster operates no database, storage or SMTP — the real work is per-permission Info.plist setup, where each permission needs its usage description key or Xcode will not build. The licence is MIT, the project has 5811 stars, 481 forks and 4 open issues, with the last push on 2026-09-12. Teams not building Swift apps for Apple platforms, or not using Xcode and Swift Package Manager, should not pick it; the FaceID status limitation and the keyless Notification permission are the two caveats to plan around.
project readme (upstream, from github) — read inline
PermissionsKit
Universal API for requesting permissions and reading their status — .authorized, .denied & .notDetermined. Each permission ships as a separate product, so the app compiles only the ones it actually uses.
Installation
In Xcode: File → Add Package Dependencies → paste URL:
https://github.com/sparrowcode/PermissionsKit
Then pick the products you need. Add only those — every permission API you link is visible to App Review, and unused ones invite questions about why the app needs them.
Permissions
Usage
Request a permission:
import PermissionsKit
import NotificationPermission
Permission.notification([.alert, .badge, .sound]).request {
// Called once the user answers the system dialog.
}
Read its status:
import PermissionsKit
import CameraPermission
let authorized = Permission.camera.authorized
[!WARNING]
FaceID can't tell .authorized from .notDetermined — both come back as .notDetermined. Only .denied is reliable.
Keys in Info.plist
Apple requires a usage description for most permissions. Get the key for a permission:
let key = Permission.bluetooth.usageDescriptionKey
[!NOTE]
Use the key itself, not the description text — Xcode won't build otherwise.
Localisation
An xliff export creates the keys for you. Doing it by hand means adding an InfoPlist.strings file, selecting the languages in the inspector, and writing the keys there:
"NSCameraUsageDescription" = "Here description of usage camera";