Trying to get NSUserNotifications to work in my app

438 Views Asked by At

I am trying to update to NSUserNotifications.

I have changed how my code is written and changed where it is place but the same thing keeps happening.

In my AnotherViewController.h

#import <UserNotifications/UserNotifications.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@interface AnotherViewController : UIViewController <UNUserNotificationCenterDelegate>

{
UNAuthorizationOptions UNAuthorizationOptionBadge;;
    UNAuthorizationOptions UNAuthorizationOptionAlert;
    UNAuthorizationOptions UNAuthorizationOptionSound;
}

@property(readonly, copy) NSString *localizedDescription;

In my AnotherViewController.m

@synthesize localizedDescription;

-(void)viewDidAppear:(BOOL)animated;{
[super viewDidAppear:YES];



NSLog(@"viewDidAppear");


UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;



[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        if (@available(iOS 14.0, *)) {
            if (settings.authorizationStatus == UNAuthorizationStatusEphemeral) {
                NSLog(@"Ephermeral");
            }
            else if (settings.authorizationStatus == UNAuthorizationStatusProvisional) {
                NSLog(@"provisional");
            }
    
  else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
      NSLog(@"authorized");
  }
   else if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
        NSLog(@"denied");
    }
   
   else if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
           NSLog(@"Not determined");
       [center requestAuthorizationWithOptions:(self->UNAuthorizationOptionBadge|self->UNAuthorizationOptionAlert|self->UNAuthorizationOptionSound)
                 completionHandler:^(BOOL granted, NSError * _Nullable error) {
                     if (! error) {
                        
                         NSLog(@"success");
                     }
                     else {
                         NSLog(@"desc%@",self.localizedDescription);
                     }
                 }];
       }
  
   }
    else {
       NSLog(@"earlier");
   }
   
}];

In my log I get Not determined and then success.

 if (! error){NSLog(@"success");}

So even though the status is Not determined the app calls the method but does not display the Alert asking for permission.
Still not sure why this is happening.

2

There are 2 best solutions below

0
user1114881 On BEST ANSWER

I finally figured this out. I had to enable the modules. I went to the Target > Build Settings and set the Enable Modules (C and Objective-C modules) to YES. It was set to NO so the modules included with UNUsersNotification weren't being used. Now I get the call for permissions. Now just have to finish figuring how to get the notification to come up when the app is in the background or not running. But that is a different post and question. Thanks

3
matt On

The main problem so far is this code:

[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
    if (settings.authorizationStatus != UNAuthorizationStatusAuthorized) {
    }
}];

That is too blunt a test. You are asking what the authorization status is not. You need to examine the authorization status to see what it is is.

If it is not "not determined", you can not cause the authorization dialog to appear to the user; the answer to the question of status is already known. The user can elect to make a change in the settings app, and you can put up a normal dialog asking the user to do that, but you cannot make the system present the authorization dialog.

Moreover, there are several ways to be authorized; "authorized" is not the only one.

So your entire approach is backwards. The correct strategy is:

  1. Call getNotificationSettingsWithCompletionHandler.

  2. In the completion handler, examine the status. Look at what it is, not at what it is not:

    a. If the status is "authorized" or "provisional" or "ephemeral", you know you are clear to go ahead and post a notification to the system.

    b. If the status is "denied", don't post a notification.

    c. If the status is "not determined", you may now call requestAuthorizationWithOptions to put up the authorization dialog, if you wish.

    • In that method's completion handler, if the BOOL is YES, you are now authorized and you are clear to post a notification.

This is a complete example that works on my machine:

#import "ViewController.h"
@import UserNotifications;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        UNAuthorizationStatus status = settings.authorizationStatus;
        if (status == UNAuthorizationStatusNotDetermined) {
            UNAuthorizationOptions opts = UNAuthorizationOptionAlert;
            [center requestAuthorizationWithOptions:opts completionHandler:^(BOOL granted, NSError * _Nullable error) {
                if (granted) {
                    NSLog(@"Hoorah");
                } else {
                    NSLog(@"User refused.");
                }
            }];
        } else {
            NSLog(@"status was %ld", status);
        }
    }];
}

@end