SPPermissions
is an API to ask for user permissions using Swift. The API provides for three UI options (list, dialog & native). The UI/UX is in an Apple style and supports iPad, dark mode, & tvOS. Also you can check the state permissions using the API.
Visit my store for iOS developers:
If you like the project, do not forget to put star ★
and follow me on GitHub:
You can check example usage in app Debts - Spending tracker for iOS and macOS. To help on SPPermission
project, see the Сooperation section.
I have migrated SPPermissions
to the new 5.0
vesion. If you find any bugs or need any of the old functionality - please create an issue or write me. If you want stay on the old version (4.x), add this to your Podfile:
pod 'SPPermissions', '4.1.4'
I recomended that you install the new version and create an issue if you have a problem. I generally response to and resolve all issues in 24-48 hours.
- Requirements
- Installation
- Usage
- Permissions
- DataSource & Delegate
- Denied alert
- Good Practices
- Keys in Info.plist
- Сooperation
- License
Swift 4.2
& 5.0
. Ready for use on iOS 11+
CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate SPPermissions
into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'SPPermissions/Notification'
Due to Apple's new policy regarding permission access you need to specifically define what kind of permissions you want to access using subspecs. For example if you want to access Camera
, Location
& Microphone
you define the following:
pod 'SPPermissions/Camera'
pod 'SPPermissions/Location'
pod 'SPPermissions/Microphone'
Available subspecs
pod 'SPPermissions/Camera'
pod 'SPPermissions/Contacts'
pod 'SPPermissions/Calendar'
pod 'SPPermissions/PhotoLibrary'
pod 'SPPermissions/Notification'
pod 'SPPermissions/Microphone'
pod 'SPPermissions/Reminders'
pod 'SPPermissions/SpeechRecognizer'
pod 'SPPermissions/Location'
pod 'SPPermissions/Motion'
pod 'SPPermissions/MediaLibrary'
pod 'SPPermissions/Bluetooth'
The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
To integrate SPPermissions
into your Xcode project using Xcode 11, specify it in File > Swift Packages > Add
:
https://github.com/ivanvorobei/SPPermissions
After integrate need add configuration. See example SPPermissionsConfiguration.xcconfig file or example project. If you don't know how add configuration file, see this short video.
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate SPPermissions
into your Xcode project using Carthage, specify it in your Cartfile
:
github "ivanvorobei/SPPermissions"
By default available all permissions. You can provide custom build flags before building the dynamic framework to only compile
with permissions you request. Open file SPPermissionsConfiguration.xcconfig in Source/SPPermissions/Supporting Files
, comment unusable permissions and rebuild:
carthage build
If you prefer not to use any of dependency managers, you can integrate SPPermissions
into your project manually. Put Source/SPPermissions
folder in your Xcode project. Make sure to enable Copy items if needed
and Create groups
.
After it need add configuration. See example SPPermissionsConfiguration.xcconfig file or example project. If you don't know how add configuration file, see this short video.
This project had separate modules for the display UI options. The interfaces are: Dialog
, List
and Native
. Each interface has delegates and a datasource. If you want see an example app, open SPPermissions.xcodeproj
and choose the Example
target.
This is a Modal alert, which was used in the previous version (<5.x). I recomend the use of this alert style when your requested permissions are less than three. Usage example:
let controller = SPPermissions.dialog([.camera, .photoLibrary])
// Ovveride texts in controller
controller.titleText = "Title Text"
controller.headerText = "Header Text"
controller.footerText = "Footer Text"
// Set `DataSource` or `Delegate` if need.
// By default using project texts and icons.
controller.dataSource = self
controller.delegate = self
// Always use this method for present
controller.present(on: self)
Native UITableViewController
with support for the iPad. Use it with more than two permissions. An example of how it is used:
let controller = SPPermissions.list([.calendar, .camera, .contacts])
// Ovveride texts in controller
controller.titleText = "Title Text"
controller.headerText = "Header Text"
controller.footerText = "Footer Text"
// Set `DataSource` or `Delegate` if need.
// By default using project texts and icons.
controller.dataSource = self
controller.delegate = self
// Always use this method for present
controller.present(on: self)
Request permissions with native alerts. You can request many permissions at once:
let controller = SPPermissions.native([.calendar, .camera, .contacts])
// Set `Delegate` if need.
controller.delegate = self
// Always use this method for request.
// You can pass any controller, this request because need implement base protocol.
controller.present(on: self)
To check the state of any permission, call enum SPPermission
:
let state = SPPermission.calendar.isAuthorized
Also available is the func isDenied
. This returns false if the permission has not been requested before.
For a customized permssions view, implement SPPermissionsDataSource
:
func configure(_ cell: SPPermissionTableViewCell, for permission: SPPermission) -> SPPermissionTableViewCell {
return cell
}
Using a delegate, you can customize texts, colors, and icons. For a default view configure with the default values. After configuration return the cell.
You can customize:
// Titles
cell.permissionTitleLabel.text = "Notifications"
cell.permissionDescriptionLabel.text = "Remind about payment to your bank"
cell.button.allowTitle = "Allow"
cell.button.allowedTitle = "Allowed"
// Colors
cell.iconView.color = .systemBlue
cell.button.allowedBackgroundColor = .systemBlue
cell.button.allowTitleColor = .systemBlue
// If you want set custom image.
cell.set(UIImage(named: "IMAGE-NAME")!)
In the delegate you can implement these methods:
// Events
func didAllow(permission: SPPermission) {}
func didDenied(permission: SPPermission) {}
func didHide(permissions ids: [Int])
// Denied alert. Show alert if permission denied.
func deniedData(for permission: SPPermission) -> SPPermissionDeniedAlertData?
You can detect permission values as follows:
let permissions = ids.map { SPPermission(rawValue: $0) }
If you don't want show an alert if a permission is denied, return nil
in the delegate. You can set the text in the alert:
func deniedData(for permission: SPPermission) -> SPPermissionDeniedAlertData? {
if permission == .notification {
let data = SPPermissionDeniedAlertData()
data.alertOpenSettingsDeniedPermissionTitle = "Permission denied"
data.alertOpenSettingsDeniedPermissionDescription = "Please, go to Settings and allow permission."
data.alertOpenSettingsDeniedPermissionButtonTitle = "Settings"
data.alertOpenSettingsDeniedPermissionCancelTitle = "Cancel"
return data
} else {
// If returned nil, alert will not show.
return nil
}
}
If you don't implement this method, the alert will appear with default text. To disable the alert you just need return nil
.
I recommend that you show the user all of the permission options, even if some of them are already allowed. But if you want to request only non-allowed permissions, use this code:
let controller = SPPermissions.list([.notification, .reminders].filter { !$0.isAuthorized } )
controller.present(on: self)
A good way to check for the need to show a dialog: check that all permissions are currently authorized by the user:
let permissions = [.notification, .reminders].filter { !$0.isAuthorized }
if permissions.isEmpty {
// No need show dialog
} else {
// Show dialog
}
If you request location services, you can show both .locationWhenInUse
& .locationAlwaysAndWhenInUse
. If the user allowed always
mode, they can also change to when in use
mode:
let controller = SPPermissions.dialog([.locationWhenInUse, .locationAlwaysAndWhenInUse])
controller.present(on: self)
You need to add some keys to the Info.plist
file with descriptions. List of keys:
- NSCameraUsageDescription
- NSContactsUsageDescription
- NSCalendarsUsageDescription
- NSMicrophoneUsageDescription
- NSAppleMusicUsageDescription
- NSSpeechRecognitionUsageDescription
- NSMotionUsageDescription
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysAndWhenInUseUsageDescription
- NSLocationAlwaysUsageDescription (iOS 10 and earlier)
- NSBluetoothAlwaysUsageDescription
- NSBluetoothPeripheralUsageDescription (iOS 12 and earlier)
Do not use the description as the name of the key.
If you use xliff localization export, keys will be create automatically. If you prefer do the localization file manually, you need to create InfoPlist.strings
, select languages in the right side menu and add keys as keys in plist-file. See:
"NSCameraUsageDescription" = "Here description of usage camera";
The use of this project is completely free. If you can make a contribution, it will help with development. Here is a list of tasks and what needs to be done:
- Add docs in source files. Add a description of public methods and parameters.
- Subtitles for this video in any of your native languages, where I tell you how to connect a configuration file.
- Fix SPM support. Now SPM ignore config flags. Issue #156
- Help me translate my app Debts - Spending tracker for other languages.
- Add an icon for tv os example target.
- Add code for
Bluetooth
request permission. For now after requestBluetooth
developers get error.
I developed SPPermissions
in an 'Apple-way'. To accomplish this, I checked 30 apps to get UI-elements for this project. I then took screenshots and re-drew the elements in Sketch. For example, the project's Allow
button is similar to the Get
button in the AppStore. Check this timelapse to see how I designed the 4.0
version of SPPermissions
:
SPPermissions
is released under the MIT license. Check LICENSE
for details.