How to get unique device id in iOS - ios

I am working on iOS app for push notification feature i need to send unique device id of iOS device to server ,in android secure androd id getting for every device,is there any way to get unique device id of iOS.
I found some answers vendor id and ad id are they unique
code:
Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID);

For get UUID you can use this code
UIDevice *currentDevice = [UIDevice currentDevice];
NSString *deviceId = [[currentDevice identifierForVendor] UUIDString];
But for push notifications you need device token and it will create after user will accept permission and UIApplication delegate method will call
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

There is no legal way to uniquely identify an iOS device. Period.
You can get only compromise solutions: IDFA, Vendor ID or APNS Device Token.
Every above-mentioned ID can change during the device lifecycle, thus they cannot be used as unique device identifiers.

for Step by step by Step Integration of APNS in your application , you can get the steps in here
iOS9 Apple says that Device Token might change each time your app is installed. So the best way is to reregister the Device token on each launch.
Step-1
There are two steps to register for push notifications. First, you must obtain the user’s permission to show any kind of notification, after which you can register for remote notifications. If all goes well, the system will then provide you with a device token, which you can think of as an “address” to this device.
This method creates an instance of UIUserNotificationSettings and passes it to registerUserNotificationSettings(_:).
UIUserNotificationSettings stores settings for the type of notification your app will use. For the UIUserNotificationTypes, you can use any combination of the following:
.Badge allows the app to display a number on the corner of the app’s icon.
.Sound allows the app to play a sound.
.Alert allows the app to display text.
The set of UIUserNotificationCategorys that you currently pass nil to allows you to specify different categories of notifications your app can handle. This becomes necessary when you want to implement actionable notifications, which you will use later
- (void)applicationDidFinishLaunching:(UIApplication *)app {
// other setup tasks here....
// Register the supported interaction types.
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
// Register for remote notifications.
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
Build and run. When the app launches, you should receive a prompt that asks for permission to send you notifications:
Tap OK and poof! The app can now display notifications.
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
if (notificationSettings.types != UIUserNotificationTypeNone) {
//register to receive notifications
[application registerForRemoteNotifications];
}
}
Here, you first check whether the user has granted you any notification permissions; if they have, you directly call registerForRemoteNotifications().
Again, methods in UIApplicationDelegate are called to inform you about the status of registerForRemoteNotifications().
// Handle remote notification registration.
- (void)application:(UIApplication *)app
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
const void *devTokenBytes = [devToken bytes];
self.registered = YES;
// send your Device Token to server
}
As the names suggest, the system calls application(:didRegisterForRemoteNotificationsWithDeviceToken:) when the registration is successful, and otherwise calls application(:didFailToRegisterForRemoteNotificationsWithError:).
- (void)application:(UIApplication *)app
didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"Error in registration. Error: %#", err);
}
Swift
let defaults = NSUserDefaults.standardUserDefaults()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// PUSH NOTIFICATION
let deviceToken = defaults.objectForKey(UserDefaultsContracts.KEY_DEVICE_TOKEN) as String?
if (deviceToken == nil) {
print("There is no deviceToken saved yet.")
var types: UIUserNotificationType = UIUserNotificationType.Badge |
UIUserNotificationType.Alert |
UIUserNotificationType.Sound
var settings: UIUserNotificationSettings = UIUserNotificationSettings( forTypes: types, categories: nil )
application.registerUserNotificationSettings( settings )
application.registerForRemoteNotifications()
}
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData!) {
print("Got token data! (deviceToken)")
var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
var deviceTokenString: String = ( deviceToken.description as NSString )
.stringByTrimmingCharactersInSet( characterSet )
.stringByReplacingOccurrencesOfString( " ", withString: "" ) as String
print( deviceTokenString )
defaults.setObject(deviceTokenString, forKey: UserDefaultsContracts.KEY_DEVICE_TOKEN)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError!) {
print("Couldn’t register: (error)")
}
}
for more information you get in Apple Documents

For Objectice-C:
UIDevice *device = [UIDevice currentDevice];
NSString *currentDeviceId = [[device identifierForVendor]UUIDString];
For Swift:
let device_id = UIDevice.currentDevice().identifierForVendor?.UUIDString

As per the Apple Documentation,
Device tokens can change, so your app needs to reregister every time
it is launched and pass the received token back to your server. If you
fail to update the device token, remote notifications might not make
their way to the user’s device. Device tokens always change when the
user restores backup data to a new device or computer or reinstalls
the operating system. When migrating data to a new device or computer,
the user must launch your app once before remote notifications can be
delivered to that device.
Never cache a device token; always get the token from the system
whenever you need it. If your app previously registered for remote
notifications, calling the registerForRemoteNotifications method again
does not incur any additional overhead, and iOS returns the existing
device token to your app delegate immediately. In addition, iOS calls
your delegate method any time the device token changes, not just in
response to your app registering or re-registering.
So the best way is to re-register for the token on each launch. For that you can call registerForPushNotifications(application) in applicationDidFinishLaunching() method.
The delegate method for the above method is didRegisterForRemoteNotificationsWithDeviceToken in which you can the deviceToken and send it to server.
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for i in 0..<deviceToken.length {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
print("Device Token:", tokenString)
}

You should receiver in
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
var deviceTokenStr = String(format: "%#", deviceToken)
deviceTokenStr = deviceTokenStr.stringByReplacingOccurrencesOfString("<", withString: "")
deviceTokenStr = deviceTokenStr.stringByReplacingOccurrencesOfString(">", withString: "")
deviceTokenStr = deviceTokenStr.stringByReplacingOccurrencesOfString(" ", withString: "")
}
Or if you want to get unique device id , you can use
let UUID = NSUUID().UUIDString

as I did in my app, you can use first generated uuid and save it in Keychain file to use it as unique device id (because uuid is changed in every running for ur app and also device token) so u can save a uuid or any custom id u generate in keychain it will remain forever even user uninstall and in install the app many times

Related

Error APNS device token not set before retrieving FCM Token for Sender ID

I am receiving messages from firebase for notifications with APNs. In firebase, I have the certificate of APNs key, with the same id in the Xcode project in Firebase that is extracted from Apple Developer.
But I don't know why this could be happening and I get this error and it is registering two tokens in the Messaging extension:
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {}}
APNS device token not set before retrieving FCM Token for Sender ID
'########'. Notifications to this FCM Token will not be delivered
over APNS.Be sure to re-retrieve the FCM token once the APNS device
token is set.
Added what I have in the AppDelegate
import Firebase
import MasivPushIosSdk
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var firebaseToken: String = ""
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self.registerForFirebaseNotification(application: application)
Messaging.messaging().delegate = self
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
func registerForFirebaseNotification(application: UIApplication) {
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
}
extension AppDelegate: MessagingDelegate, UNUserNotificationCenterDelegate {
//MessagingDelegate
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
self.firebaseToken = fcmToken!
print("Firebase token: \(fcmToken)")
}
//UNUserNotificationCenterDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("APNs received with: \(userInfo)")
}
}
This is a simulator only log. You can safely ignore it. The reason you get this is that Firebase tries to create a mapping from the FCM token to the APNS token so it can send the APNS messages to the iOS devices. However, there is no APNS token on the simulator so the mapping fails.
Try testing it on an actual device to see if you still get the error.
I spent a long time on this issue. I finally got it working with remote messages.
It can be caused by a few main reasons.
GoogleService-Info.plist wasn't added to your project through xcode (checkmark copy over files if needed)
GoogleService-Info.plist should show up in Build Phases -> Copy Bundle Resources. If 1 is done, it would be here automatically.
(If you are working with React Native) Make sure your GoogleService-Info.plist info points to the same Firebase Project that your Javascript code has.
Apple Service Keys, and firebase project where this key is used should point to the same apple bundle identifier.
(If you are working with React Native) Put this in componentDidMount()
const authStatus = await firebase.messaging().requestPermission();
if (authStatus === 1) {
let fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log('Firebase Push Token is:', fcmToken);
}
}
Finally make sure your Device can connect to the internet properly. I was stuck here, my iPhone X had 2 of 3 bars, but did not connect to the internet while using same wifi as my development laptop. My laptop had no issues so I assumed my phone was connecting also ok. More than a day was wasted because I assumed. So, just double check your phone's connection works.
For more info:
A) If working Natively: https://firebase.google.com/docs/cloud-messaging/ios/client
B) If using React Native: https://rnfirebase.io/messaging/usage/ios-setup
Note: Do not mix A and B. One is meant for native IOS, other is React Native.
p.s. I added React native since i came across your question in my searches while using it.
Make sure you don't rename the auth key file
In my case, I had renamed the auth key file to something else and that was causing the issue. I tried naming it back to the default format AuthKey_<KeyID>.p8 and everything started working.
This might be late, but the error
APNS device token not set before retrieving FCM Token for Sender ID
'########'. Notifications to this FCM Token will not be delivered over
APNS.Be sure to re-retrieve the FCM token once the APNS device token
is set.
was sorted for me by adding this
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Yay! Got a device token 🥳 \(deviceToken)")
Messaging.messaging().setAPNSToken(deviceToken, type: .unknown)
}
In our case, we noticed a log above of it:
The project's Bundle ID is inconsistent with either the Bundle ID in 'GoogleService-Info.plist'
So, the case was: our app's Bundle Identifier was different from which we used to create iOS app for our Firebase project.
Making them same, solved the issue.
I hope this will help to someone, I had the same issue, and after long debugging and reading a lot of posts, this is the solution that worked for me: (Worked on real device on WiFi (no sim))
In Pods file:
target 'YOUR APP' do
config = use_native_modules!
pod 'FirebaseCore', :modular_headers => true
pod 'Firebase', :modular_headers => true
pod 'FirebaseMessaging', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
$RNFirebaseAsStaticFramework = true
Then in AppDelegate.h
#import <UserNotifications/UNUserNotificationCenter.h>
#import <RNFBMessaging+FIRMessagingDelegate.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UIApplicationDelegate,UNUserNotificationCenterDelegate, FIRMessagingDelegate>
#property (nonatomic, strong) UIWindow *window;
Then in AppDelegate.mm
#implementation AppDelegate
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(#"FCM registration token: %#", fcmToken);
// Notify about received token.
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:#"token"];
[[NSNotificationCenter defaultCenter] postNotificationName:
#"FCMToken" object:nil userInfo:dataDict];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *str = [NSString stringWithFormat:#"Device Token=%#",deviceToken];
NSLog(#"This is device token%#", deviceToken);
//NSString *deviceTokenString = [deviceToken description];
[FIRMessaging messaging].APNSToken = deviceToken;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
[[UIApplication sharedApplication] registerForRemoteNotifications];
RCTAppSetupPrepareApp(application);
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
//...OTHER CODE HERE
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// ...
}];
[[FIRMessaging messaging] setDelegate:self];
return YES;
}
Error in the logs of the phone/simulator
2023-01-28 21:11:53.907821+0100 App[16955:1733197] 10.4.0 - [FirebaseMessaging][I-FCM002022] APNS device token not set before retrieving FCM Token for Sender ID 'XXXXXXXXX'.Be sure to re-retrieve the FCM token once the APNS device token is set.
2023-01-28 21:11:53.908157+0100 App[16955:1733197] 10.4.0 - [FirebaseMessaging][I-FCM002022] Declining request for FCM Token since no APNS Token specified
⚡️ WebView loaded
⚡️ [log] - AppModule, running the app code.
⚡️ [log] -
The token must be set on the messaging component.
In AppDelegate.swift, you must have the following handler
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
}
with this instruction
Messaging.messaging().apnsToken = deviceToken
Full code is
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
Messaging.messaging().token(completion: { (token, error) in
if let error = error {
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
} else if let token = token {
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: token)
}
})
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}
This is explained in the documentation of the Ionic framework, detailing how to setup Firebase Messaging for iOS.
https://capacitorjs.com/docs/guides/push-notifications-firebase#add-initialization-code
Note - with this setup, notification will work on both the iOS Simulator provided by XCode and native devices.

How to handle push notification allow from settings in iOS

I have Integrated the push notification in my app. I am getting the device token in my AppDelegate and sending to the server in my LoginViewController. When alert comes if user click on "Don't allow" I am not calling my device registration service. But I have no idea how to handle this scenario.
If user click on don't allow in the push notification alert and go inside the app, then he open device settings and enable the push notification.
In this case how can I call my device registration service?
Please help me
Thanks
Actually there is no delegate for it to observe that user changed the status for push notifications.
But you can check by using this method in applicationDidBecomeActive: method like this
Objective C :
iOS 8 and above
if (![[UIApplication sharedApplication] isRegisteredForRemoteNotifications]){
NSLog(#"push notifications are disabled");
}
For iOS 10
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone) {
NSLog(#"push notifications are disabled");
}
Swift :
iOS 8 and above
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
NSLog(#"push notifications are enabled");
} else {
NSLog(#"push notifications are disabled");
}
For iOS 10
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .denied {
NSLog(#"push notifications are disabled");
}
})
Hope it helps.
Note
Any changes in the settings restart the app.
so If user turn on the notification from settings then your app will be restarted and you will get the device token in app-delegate and you can send it to your server. if your login is save locally and you were sending device_token in login api, then you need to use a separate service to send device_token to server.
In AppDelegate
If user Allow Notification, the token will be returned in func bellow and you will call your service to sending to your server
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
}
If user Don't Allow Notification, you will receive error in func bellow
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
}

How to get notification additionaldata(payloadData) that was at AppDelegate' didFinishLunchingWithOptions if the user didn't open the notification

I am currently using OneSignal for notification service to my app.I really need a help with accessing notification additionaldata(payload data) from AppDelegate inside didFinishLunchingWithOption where OneSignal API can give me like this.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var data : [NSObject : AnyObject]!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let oneSignal = OneSignal(launchOptions: launchOptions, appId: "48755d3d-abc0-4bac-8f71-095729bb3a65") { (message, additionalData, isActive) in
NSLog("OneSignal Notification opened:\nMessage: %#", message)
if additionalData != nil {
NSLog("additionalData: %#", additionalData)
self.data = additionalData
print(self.data)
}
}
oneSignal.enableInAppAlertNotification(true)
return true
}
}
but,I can only get the data if user click notification when appear or open it from notification center.So,if user neglect that notification without tapping when appear or without swiping or tapping from notification center,how do i get the additional data?
Actually,I want to store all payload data every time it comes into my device at realm database and fetch the data from my server according to that payload data.
You should use application(_:didReceiveRemoteNotification:fetchCompletionHandler:).
If you have enabled remote notifications background mode most of your notifications will be delivered even if the app is not running in the foreground. The only caveat being that the app must have been launched (since notifications are being pushed the user has done this) and it mustn't have been force-quit by the user.
More info in Apple's docs about that specific method.
Or in the "Local and Remote Notification Programming Guide's" notification handling chapter
You can extract all the payload in did finishLaunching by following method..
Let data = launchOptions.objectForKey(UIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationUIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationKey)

Parse iOS Swift Push Notification History

I am using Parse Push Notifications with Swift (iOS 8). The problem is when app is closed and you recieve multiple notifications, they will show in notifications alert. When I touch one of the notification it will open my app......but it will clear all notifications in notification alert view (not sure what is called). So as result all of my push notifications are lost. And I need them since they have specific payload that my app needs.
So basicly, all I need is data from received notification (not just from the one I opened).
I am using this code that Parse recommends. When app is closed and is opened with push, this function is called. I use constant let = notificationPayload to get info of payloads from push notifications. But I only get data from one push.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Enable storing and querying data from Local Datastore.
// Remove this line if you don't want to use Local Datastore features or want to use cachePolicy.
Parse.enableLocalDatastore()
// ****************************************************************************
// Uncomment this line if you want to enable Crash Reporting
// ParseCrashReporting.enable()
//
// Uncomment and fill in with your Parse credentials:
Parse.setApplicationId("+++++", clientKey: "++++++++")
//
// If you are using Facebook, uncomment and add your FacebookAppID to your bundle's plist as
// described here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/
// Uncomment the line inside ParseStartProject-Bridging-Header and the following line here:
// PFFacebookUtils.initializeFacebook()
// ****************************************************************************
PFUser.enableAutomaticUser()
let defaultACL = PFACL();
// If you would like all objects to be private by default, remove this line.
defaultACL.setPublicReadAccess(true)
PFACL.setDefaultACL(defaultACL, withAccessForCurrentUser:true)
if application.applicationState != UIApplicationState.Background {
// Track an app open here if we launch with a push, unless
// "content_available" was used to trigger a background push (introduced in iOS 7).
// In that case, we skip tracking here to avoid double counting the app-open.
// Extract the notification data.
if let notificationPayload = launchOptions? [UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
// notificationPayload have payload of only one push notification.
}
let preBackgroundPush = !application.respondsToSelector("backgroundRefreshStatus")
let oldPushHandlerOnly = !self.respondsToSelector("application:didReceiveRemoteNotification:fetchCompletionHandler:")
var noPushPayload = false;
if let options = launchOptions {
noPushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil;
}
if (preBackgroundPush || oldPushHandlerOnly || noPushPayload) {
PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
}
}
if application.respondsToSelector("registerUserNotificationSettings:") {
let userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound
let settings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
} else {
let types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Alert | UIRemoteNotificationType.Sound
application.registerForRemoteNotificationTypes(types)
}
return true
}
Any goot info, webpage, tutorial for this? Parse.com documentation is useless since apparently people get only one notification when app is closed.
If your push notifications contain important payload, you will probably have to save that payload somewhere else (Parse cloud data, for instance).
This way, even if iOS ditches your push notifications (or if the user decided to discard them) - your payload will be always available.
When the application starts up - look up for that payload in the database and act accordingly.
I found what was causing my Notifications to disappeare. I had this code in which would erase notifications:
UIApplication.sharedApplication().applicationIconBadgeNumber = 1
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
UIApplication.sharedApplication().cancelAllLocalNotifications()

Identify "Not Determined" case for Local Notifications settings

As of iOS8 you to need to register and prompt the user for the use of Local Notifications. Therefore I'd like to implement a way to double check these permissions.
How can I check for the case of Local Notifications settings being not determined/not set yet? So far I only know how to check for Local Notifications being granted or denied, like this …
var currentStatus = UIApplication.sharedApplication().currentUserNotificationSettings()
var requiredStatus:UIUserNotificationType = UIUserNotificationType.Alert
if currentStatus.types == requiredStatus {
… //GRANTED
} else {
… //DENIED
}
The problem using this is I also get a Denied if there is nothing set so far. How can I differentiate all 3 cases?
Granted (Notification, Alert Type)
Denied (Notification, Alert Type)
Undefined/Not set yet (therefore local notification app settings not created yet)
As an alternative solution it would be helpful to have a comparable delegate method to CoreLocation's authorization didChangeAuthorizationStatus in order to react on the user's selection on the permissions alert. Is there something like this in order to get the state of user interaction with the privacy alert for local notifications?
The solution I implemented :
In app delegate, I detect when didRegisterUserNotificationSettings is shot. And I save in userdefaults a bool to true :
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "notificationsDeterminedKey")
NSUserDefaults.standardUserDefaults().synchronize()
}
And when I need to know the status :
if NSUserDefaults.standardUserDefaults().boolForKey("notificationsDeterminedKey") {
let grantedSettings = UIApplication.sharedApplication().currentUserNotificationSettings()
if grantedSettings.types == UIUserNotificationType.None {
// Denied
} else {
// Granted
} else {
// Not Determined
}
I just found an appropriate UIApplication delegate method that helps to solve this:
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:
(UIUserNotificationSettings *)notificationSettings {
You can find more details on this in WWDC14 Session 713 "What’s New in iOS Notifications".

Resources