I have searched a lot to try to find a specific solution to this problem. I have an app that uses the former UILocalNotification system to send local notifications, and this still works fine under iOS 10.3.3. However, I have tried to convert this to the new UNNotification system because the former system is deprecated. No matter whether I try a UNCalendarNotificationTrigger or a UNTimeIntervalNotificationTrigger, the delegate does not receive a call. Here is the code for the triggering viewcontroller.
if (isItTime){
NSCalendar *currentCalendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
[currentCalendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [currentCalendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitTimeZone fromDate:[now dateByAddingTimeInterval:30]];
// components.second = 0;
NSLog(@"trigger components: %@", components);
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:components repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"invite" content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Something went wrong: %@",error);
}
}];
[self.currentLocalNotificationRequests addObject:request];
return request;
}else{
return nil;
}
And here is the code for the delegate (appdelegate) didFinishLaunching:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// Enable or disable features based on authorization.
NSLog(@"_prefix:set($class $method $line)");
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
if(granted == YES){
[storage setBool:YES forKey:@"permission granted"];
[storage setBool:YES forKey:@"alert permission granted"];
[storage setBool:YES forKey:@"sound permission granted"];
}else{
NSLog(@"No permission granted");
[storage setBool:NO forKey:@"permission granted"];
};
}];
Code for the appdelegate to get the notifications:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
NSLog(@"appdelegate - center didReceiveNotificationResponse");
NSString *actionIdentifier = response.actionIdentifier;
UNNotification *notification = response.notification;
if([actionIdentifier isEqual:@"com.apple.UNNotificationDefaultActionIdentifier"] || [actionIdentifier isEqual:@"com.apple.UNNotificationDismissActionIdentifier"]){
}else{
BOOL accept = [actionIdentifier isEqual:@"ACCEPT_IDENTIFIER"];
BOOL stop = [actionIdentifier isEqual:@"DECLINE_IDENTIFIER"];
BOOL doNotDisturb = [actionIdentifier isEqual:@"DO_NOT_DISTURB_IDENTIFIER"];
if (accept){NSLog(@"accept");
[self handleAcceptActionWithNotification:notification];
}
else if (stop){NSLog(@"stop");
[self handleDeclineActionWithNotification:notification];
}
else if(doNotDisturb) {NSLog(@"do not disturb");
[self handleDoNotDisturbActionWithNotification:notification];
};
}
completionHandler();
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(@"appdelegate willPresentNotification");
UNNotificationRequest * request = notification.request;
NSString * actionIdentifier = request.identifier;
if([actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier] || [actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]){
}else{
if([actionIdentifier isEqualToString:@"invite"]){
NSLog(@"app delegate notification received while in foreground");
}
}
completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);
}
Here is the NSLog of the triggering code:
<NSDateComponents: 0x146d51c0>
TimeZone: America/Chicago (CDT) offset -18000 (Daylight)
Calendar Year: 2017
Month: 10
Leap month: no
Day: 29
Hour: 14
Minute: 3
Second: 4
It is very clear that appdelegate methods are not being called by the system (I did put the app in background before the notification time, so the didReceiveNotification method should have been called.
If anyone can help, I would appreciate it!
Also, this code in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveNotificationFromAppDelegate:)
name:kAppDelegateNotification
object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationBecameActive) name:UIApplicationDidBecomeActiveNotification object:nil];
self.currentLocalNotificationRequests = [[NSMutableArray alloc]init];
/*
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkDndIndicator) name:UIApplicationDidBecomeActiveNotification object:nil];
*/
UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:@"ACCEPT_IDENTIFIER" title:NSLocalizedString(@"Continue notifications", nil) options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:@"DECLINE_IDENTIFIER" title:NSLocalizedString(@"Stop notifications", nil) options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *doNotDisturbAction = [UNNotificationAction actionWithIdentifier:@"DO_NOT_DISTURB_IDENTIFIER" title:NSLocalizedString(@"Start Do Not Disturb", nil) options:UNNotificationActionOptionAuthenticationRequired];
NSArray *actions = [NSArray arrayWithObjects:acceptAction, declineAction, doNotDisturbAction, nil];
// NSArray *intentIdentifiers = [NSArray arrayWithObjects:@"none", nil];
UNNotificationCategory *invite = [UNNotificationCategory categoryWithIdentifier:@"com.nelsoncapes.localNotification" actions:actions intentIdentifiers: @[] options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObjects:invite, nil];
[center setNotificationCategories:categories];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// Enable or disable features based on authorization.
NSLog(@"request granted");
}];
And code to start the trigger process:
-(UNNotificationRequest *)startLocalNotification:(NSDate *)fireDate :
(NSMutableDictionary *)userInfo{
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllPendingNotificationRequests];
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"TimeChime Alert", nil);
content.body = NSLocalizedString(@"Click to Stop or Change Timer",nil);
content.categoryIdentifier = @"com.nelsoncapes.localNotification";