17

I'm currently using Xcode6 beta (first version). Using parse.com, I'm trying to implement push notifications. In my app delegate, I have

  [application registerForRemoteNotifications];

When I run it on my ios8 beta iPhone, the app does not ask if I would like to enable push notifications, and the corresponding application:didRegisterForRemoteNotificationsWithDeviceToken: is never called. However, when I tried running it on an ios7 iPhone, the app crashed and I received an unrecognized selector error for the registerForRemoteNotifications method.

Then, I tried running it on a previous version of Xcode (version 5.0), but I received the compile error no visible @interface declares registerForRemoteNotifications

I'm assuming this error has to do with bugs with the transition to iOS 8, but I'm not sure how I can resolve this issue.

Mahir
  • 1,684
  • 5
  • 31
  • 59

5 Answers5

29

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

#ifdef __IPHONE_8_0
  //Right, that is the point
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
    //register to receive notifications
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif

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
Community
  • 1
  • 1
Madao
  • 3,756
  • 1
  • 22
  • 16
  • 10
    This answer, which you have also posted verbatim here: http://stackoverflow.com/a/24488562/1146823, does not properly implement a runtime check for whether or not you're running on iOS 8. For those who need to support both iOS 7 and 8, it's worth clicking through to that other answer and reading the comments there for the correct way to implement a runtime check. – dmur Sep 15 '14 at 20:24
  • 15
    This 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:54
  • @GregG I don't know what makes you say that. The docs specifically say: "Note: these callbacks will be made only if the application has successfully registered for user notifications with registerUserNotificationSettings:" – Mazyod Oct 24 '14 at 12:50
  • 4
    The docs indicate that registerForRemoteNotifications should be called every time the app launches to ensure an updated token is obtained. The latest Remote Notifications PG (10/31/14) states that the didRegisterUserNotificationSettings will only be called once when the user responds to the alert, so placing the call to registerForRemoteNotifications in that callback will result in it only every being called once. Also, the latest doc shows an example with both the registerUserNotificationSettings: and registerForRemoteNotifications called sequentially in didFinishLaunchingWithOptions: – archsten Nov 11 '14 at 00:49
  • Please excuse me: I misread the docs regarding the didRegisterUserNotificationSettings callback. It is called every time, but the alert is only shown once. Thus, it should be OK to place the registerForRemoteNotifcations call there, although the example in the docs is as I previously stated with it in the didFinishLaunchingWithOptions: method. – archsten Nov 11 '14 at 00:59
  • they dramatically changed the way it works in iOS 8. And yes, didRegister called only once. So, if your app provides it's own APNS switcher you have to cache obtained deviceToken – vaddieg Nov 17 '14 at 14:18
  • @archsten, Please provide a link with the docs that states that. – Iulian Onofrei Feb 13 '15 at 13:17
5

A couple of observations:

  • the question was using REMOTE, not local
  • some questions deal with local, that is a completely different thing
  • I agree that answer time can be very long, but you must implement call backs (aka delegate methods), as other people pointed out
  • do NOT test against compiler flag, is conceptually and practically wrong
  • test presence of selectors as in this code:

    func registerForPushForiOS7AndAbove(){
    
    UIApplication.sharedApplication()
    let application = UIApplication.sharedApplication()
    if application.respondsToSelector(Selector("registerUserNotificationSettings:")) {
    
        let notifSettings = UIUserNotificationSettings(forTypes: .Sound | .Alert | .Badge,
            categories: nil)
    
        application.registerUserNotificationSettings(notifSettings)
        application.registerForRemoteNotifications()
    
    }
    else{
        application.registerForRemoteNotificationTypes( .Sound | .Alert | .Badge )
    }
    

    }

(don't miss UIBackgroundModes in PList.. can be done in Capabilities)

ingconti
  • 10,876
  • 3
  • 61
  • 48
2

In iOS 8 the system won't ask the user to allow your app to send Push (Remote) Notifications, it's allowed by default.

The user may opt-out from allowing Notifications from your app on Settings > Yor App > Notifications > Allow Notifications.

Lucien
  • 8,263
  • 4
  • 30
  • 30
  • When I updated my iPhone 4S from 7.1.2 to 8.0.2, the push stopped working while it was working like a charm on my iPhone 5 8.0.2. I had to opt-in the "background update" row in the Settings > Yor App path to have it work. – Imotep Oct 01 '14 at 13:08
  • In some versions of iOS registerForRemoteNotifications() is needed in others it is not. I solved this by checking whether SharedApplication responds to the selector "registerForRemoteNotifications:". If it did then I called it. – Josh Woodcock Jul 05 '15 at 20:48
2

Just use this snippet of code to register for notifications in iOS 8:

UIUserNotificationSettings *settings = 
    [UIUserNotificationSettings 
        settingsForTypes: (UIUserNotificationTypeBadge | 
                           UIUserNotificationTypeSound |                 
                           UIUserNotificationTypeAlert) 
        categories:nil];

[[UIApplication sharedApplication] registerUserNotificationSettings:settings];

Use UIUserNotificationType instead of UIRemoteNotificationType!

Jack Allen
  • 549
  • 2
  • 5
  • 19
Kai Burghardt
  • 1,493
  • 16
  • 16
1

registerForRemoteNotifications method is available from iOS8.

application:didRegisterForRemoteNotificationsWithDeviceToken: delegate method is called only when registration is success , if any failure occurs it will call application:didFailToRegisterForRemoteNotificationsWithError: method.

For more information go through : UIApplication Class reference

Also check notification is enable for the app Settings -> Notifications -> YourApp -> Enable_Notifications

According to the documentation, neither of the callbacks will happen until the device has a persistent connection with the push server. So if there is no wifi or data connection available, the callbacks won't happen - and apple doesn't regard this as an error condition. only errors that can happen to cause the didFail... callback are an incorrect certificate/app permissions issue (a development problem), or the user declined permission.

Please go through Push notification programming guide

Jack Allen
  • 549
  • 2
  • 5
  • 19
Yatheesha
  • 10,412
  • 5
  • 42
  • 45
  • I have both of the delegate methods implemented, but neither are called – Mahir Jun 30 '14 at 08:38
  • @Mahir Check internet connection is available or not . – Yatheesha Jun 30 '14 at 09:05
  • The internet has, in fact, been strangely slow for the ios8 device. Since the `registerForRemoteNotifications` is only ios8, to try ios7 devices, do I use `registerForRemoteNotificationTypes:`? – Mahir Jun 30 '14 at 09:36
  • @Mahir Its always recommended to use new api's , check os version to call specific methods. – Yatheesha Jun 30 '14 at 09:42
  • Tested on iOS9, `didRegisterForRemoteNotificationsWithDeviceToken` is called even there's no internet connection. But it needs to be called once online to let operating system to store token. – ugur Oct 26 '15 at 08:42
  • also - i see didRegisterForRemoteNotificationsWithDeviceToken being called even before user agreed (dialog still visible) on iOS 9 – Cherpak Evgeny Oct 29 '15 at 08:04