How can I get the Device Token for remote notification in iOS 8?
I used the method didRegisterForRemoteNotificationsWithDeviceToken
in AppDelegate
in iOS < 8, and it returned the device token. But in iOS 8, it does not.

- 6,298
- 1
- 26
- 41

- 1,023
- 1
- 10
- 16
-
This really worked..! http://stackoverflow.com/questions/4086599/why-didregisterforremotenotificationswithdevicetoken-is-not-called/26115072#26115072 – Apr 12 '16 at 10:46
7 Answers
Read the code in UIApplication.h.
You will know how to do that.
First:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
add Code like this
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
#ifdef __IPHONE_8_0
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert
| UIUserNotificationTypeBadge
| UIUserNotificationTypeSound) categories:nil];
[application registerUserNotificationSettings:settings];
#endif
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
if you not using both Xcode 5 and Xcode 6 ,try this code
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound
|UIRemoteNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
(Thanks for @zeiteisen @dmur 's remind)
Second:
Add this Function
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
//handle the actions
if ([identifier isEqualToString:@"declineAction"]){
}
else if ([identifier isEqualToString:@"answerAction"]){
}
}
#endif
And your can get the deviceToken in
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
if it still not work , use this function and NSLog the error
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
-
4This. Sophomorically enough, Apple failed to update their documentation for `UIUserNotificationSettings` or `UIApplication` talking about how this is required for iOS 8. It's buried in their API diffs instead. – Hyperbole Aug 19 '14 at 19:19
-
27This will crash on iOS versions below iOS 8. #ifdef is a COMPILER function, and is evaluated at compile time. You still need a run-time check! – Dan VanWinkle Aug 26 '14 at 14:58
-
-
That's not true. Try running this code on an iOS 7 or below device. It will crash. If you compile the code on the latest Xcode, ONLY the first half of the code will be ran, and the #else part will not even be compiled into code. – Dan VanWinkle Aug 28 '14 at 03:17
-
__IPHONE_8_0 is work in XCode5. I'm using this code in my project.I try it in iOS6 devise. – Madao Aug 28 '14 at 03:19
-
I use xcode 6 beta 6 and #ifdef __IPHONE_8_0 work with below ios 8. So I must change to `if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)` – quang thang Aug 28 '14 at 07:41
-
4Use this macro to check for iOS 8: #define isAtLeastiOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) . __IPHONE_8_0 is not a good check because you want this code to continue to run on future versions also. – er0 Sep 11 '14 at 22:01
-
@er0 Yes, but __IPHONE_8_0 will also be defined in future versions. Just as __IPHONE_7_0 works under iOS 8... so really, you can use either. – dmur Sep 15 '14 at 18:53
-
@er0 Take a look at the header file Availability.h and you'll see what I mean... you can command-click on __IPHONE_8_0 to bring up the file. There you'll see that every version up to and including the current is #defined, not just the current one. – dmur Sep 15 '14 at 19:02
-
2That said, in this case the #ifdef is unnecessary, unless your team is using both Xcode 5 and Xcode 6. Instead you should do an `if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {` check, as zeiteisen does in his answer. – dmur Sep 15 '14 at 20:09
-
1This is actually incorrect and should be voted down. The application:didRegisterUserNotificationSettings: method will not be called until you call the UIApplication registerForRemoteNotification method. You don't call that in that method. – Greg G Sep 20 '14 at 22:56
-
@GregG `application:didRegisterUserNotificationSettings:` will be called after `[application registerUserNotificationSettings:]` (user will be prompted to allow notifications). – derpoliuk Sep 21 '14 at 11:41
-
6Little bit correction for deprecated enum UIRemoteNotificationType: NS_ENUM_DEPRECATED_IOS(3_0, 8_0, "Use UIUserNotificationType for user notifications and registerForRemoteNotifications for receiving remote notifications instead."); So, for iOS 8 and later you must use UIUserNotificationTypeBadge, UIUserNotificationTypeSound, UIUserNotificationTypeAlert. (UIUserNotificationType for new versions, UIRemoteNotificationType - for older). Enums defined in
and – KepPM Sep 23 '14 at 14:04 -
If you want the code to compile under xcode 5.x there is also this answer http://stackoverflow.com/a/25871600/756809 – Shai Almog Sep 23 '14 at 18:35
-
`#ifdef` is not a good way to support new APIs, it means your app will crash on devices running iOS7. `respondsToSelector` is the correct way to do the check in all cases. – mcfedr Oct 06 '14 at 06:56
-
Am I misunderstanding what is supposed to happen here? I have added this code, but the application:didRegisterForRemoteNotificationsWithDeviceToken never gets called on my iOS8 iPhone. didRegisterUserNotificationSettings **is** called, is there something more that I have to do there? – Maury Markowitz Jan 22 '15 at 15:25
-
You have to call `completionHandler();` when you are done in `handleActionWithIdentifier` as mentioned in Apple Docs – CyberMew Feb 06 '15 at 04:57
-
You saved my skin! I've been having troubles with push notifications for about 3 days now ... and this post had the key! I wasn't receiving new tokens even if I change from develop to adhoc apps .... I believe the problem was that I did't implement didRegisterUserNotificationSettings ... Once again thanks a lot! – BrunoX Feb 18 '15 at 10:02
The way to register for iOS 8 and keep supporting older versions
UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
|UIUserNotificationTypeSound
|UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
and in the app delegate add
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[application registerForRemoteNotifications];
}
iOS8 can receive silent notificaions without asking for permission. Call
- (void)registerForRemoteNotifications
. After this application:didRegisterForRemoteNotificationsWithDeviceToken:
will be called
Note: the callback with the token is only called if the application has successfully registered for user notifications with the function below or if Background App Refresh is enabled.
Check the Settings for you app if any notification type is enabled. If not, you will not get a device token.
You are now able to obtain silent notifications with
aps {
content-available: 1
}
in the notification payload
But notifications that appear still needs permission. Call
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[application registerUserNotificationSettings:notificationSettings];
This code should ask for permission.
You should now be ready to get push notifications

- 7,078
- 5
- 50
- 68
-
1thank you for the `OS8 can receive silent notifications without asking for permission` bit. That was driving me crazy and this is the only place I found that helpful bit! – sbauch Feb 18 '15 at 22:39
-
@zeiteisen, in your first `if` statement, you should be using `UIUserNotificationTypeSound` instead of `UIRemoteNotificationTypeSound`, since `UIRemoteNotificationType` is deprecated in iOS 8. – Tanner Semerad Feb 25 '15 at 19:52
-
Can someone explain why the callback with the token is only called when Background App Refresh is enabled? I though it should be called when the Push Notification permission is enabled... – guilherme.minglini Jan 20 '16 at 18:49
In my case I had made the necessary updates to request push notification access for iOS 7 and iOS 8, however I had not implemented the new callback for when an iOS 8 user grants access. I needed to add this method to my app delegate.
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[application registerForRemoteNotifications];
}

- 38,547
- 26
- 130
- 141
If you are using Xamarin.iOS to build your mobile application, you can use this snippet of code to request push notification registration
if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))
{
UIUserNotificationType userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(userNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
else
{
UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}
Also you will need to override DidRegisterUserNotificationSettings
method to get the device token returned from the APNS server:
public override void DidRegisterUserNotificationSettings(UIApplication application, UIUserNotificationSettings notificationSettings)
{
application.RegisterForRemoteNotifications();
}

- 24,792
- 68
- 164
- 231
The answer of Madao (https://stackoverflow.com/a/24488562/859742) is right but....
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
should be more "correct"
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
Those flags have the same bit mask values and thats why both would work but UIUserNotificationSettings
requires UIUserNotificationType
not UIRemoteNotificationType
.
Apart from that I would call
[application registerUserNotificationSettings:settings];
In the AppDelegate
method (depending on the granted rights),
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings

- 1
- 1

- 11,644
- 6
- 63
- 79
-
-
1UIUserNotificationTypeBadge and UIRemoteNotificationTypeBadge are same bit masks but mean different things =) – Ilker Baltaci Nov 21 '14 at 08:37
I thing the better way to keep backward compatibility we can go with this approach, it is working for my case hope work for you. Also pretty easy to understand.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}

- 852
- 12
- 21
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
[application registerForRemoteNotifications];

- 7,181
- 7
- 63
- 111

- 2,988
- 1
- 21
- 43