Permission Prompts for the Apple SDK
Request additional system permissions (e.g., location) from users using Opt-in Actions.
The Airship SDK automatically handles push notification permissions. For additional permissions like location, you can use Opt-in Actions to prompt users using native permission prompts.
Opt-in Actions are a special type of ActionA configurable behavior that occurs when a user interacts with your message, e.g., opening a web page. that are handled by PermissionsManager. For an overview of all supported actions and where they are available, see the Actions guide.
Supported Opt-in Types
- Push — Handled automatically by the SDK (no implementation needed)
- Location — Requires implementing a custom
PermissionDelegate
Implementing Location Opt-in
To implement Location Opt-in, create a custom PermissionDelegate and register it with PermissionsManager to handle location permissions.
Create a Location Permission Delegate
Creating a location permission delegate
import Foundation
import CoreLocation
import AirshipCore
import Combine
class LocationPermissionDelegate: AirshipPermissionDelegate {
let locationManager = CLLocationManager()
@MainActor
func checkPermissionStatus() async -> AirshipCore.AirshipPermissionStatus {
return self.status
}
@MainActor
func requestPermission() async -> AirshipCore.AirshipPermissionStatus {
guard (self.status == .notDetermined) else {
return self.status
}
guard (AppStateTracker.shared.state == .active) else {
return .notDetermined
}
locationManager.requestAlwaysAuthorization()
await waitActive()
return self.status
}
var status: AirshipPermissionStatus {
switch(locationManager.authorizationStatus) {
case .notDetermined:
return .notDetermined
case .restricted:
return .denied
case .denied:
return .denied
case .authorizedAlways:
return .granted
case .authorizedWhenInUse:
return .granted
@unknown default:
return .notDetermined
}
}
}
@MainActor
private func waitActive() async {
var subscription: AnyCancellable?
await withCheckedContinuation { continuation in
subscription = NotificationCenter.default.publisher(for: AppStateTracker.didBecomeActiveNotification)
.first()
.sink { _ in
continuation.resume()
}
}
subscription?.cancel()
}#import <CoreLocation/CoreLocation.h>
#import <AirshipCore/AirshipCore.h>
@interface LocationPermissionDelegate : NSObject <UAPermissionDelegate>
@property (nonatomic, strong) CLLocationManager *locationManager;
@end
@implementation LocationPermissionDelegate
- (instancetype)init {
self = [super init];
if (self) {
_locationManager = [[CLLocationManager alloc] init];
}
return self;
}
- (UAPermissionStatus)checkPermissionStatus {
return [self status];
}
- (void)requestPermissionWithCompletionHandler:(void (^)(UAPermissionStatus))completionHandler {
if ([self status] != UAPermissionStatusNotDetermined) {
completionHandler([self status]);
return;
}
if ([UAAppStateTracker shared].state != UAAppStateActive) {
completionHandler(UAPermissionStatusNotDetermined);
return;
}
[self.locationManager requestAlwaysAuthorization];
// Wait for app to become active and check status
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler([self status]);
});
}
- (UAPermissionStatus)status {
switch (self.locationManager.authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
return UAPermissionStatusNotDetermined;
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
return UAPermissionStatusDenied;
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorizedWhenInUse:
return UAPermissionStatusGranted;
default:
return UAPermissionStatusNotDetermined;
}
}
@endRegister the Permission Delegate
After creating a location PermissionDelegate, register it with PermissionsManager after takeOff:
Registering the permission delegate
Airship.permissionsManager.setDelegate(
LocationPermissionDelegate(),
permission: .location
)LocationPermissionDelegate *delegate = [[LocationPermissionDelegate alloc] init];
[[UAirship permissionsManager] setDelegate:delegate permission:UAPermissionLocation];Categories