0

我有一个应用程序通过 UNNotification 本地通知每 x 分钟提醒用户一次。如果用户没有响应,iOS 锁定屏幕会显示一系列横幅,要求用户响应。大多数情况下,当应用程序处于后台时,用户点击横幅(点击主页按钮后)会触发 UNNotification 中心委托。但是,有时用户点击最新的横幅不会触发委托e。注意:这不是关于代表在没有用户点击的情况下未接听电话的问题:我知道这是不可能的。当用户点击横幅中的操作按钮时,为什么 iOS 不会偶尔触发应用委托?注意:我会跟踪待处理的本地通知的数量,并且从不超过 64 的系统限制。

应用委托:

- (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.
                          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"];
                          };
                      }];
}

    #pragma mark UNNotificationCenter setup

    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.
                          }];

    #pragma mark UNNotification received in background
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        NSLog(@"notification settings were changed");
        NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
        [storage setBool:YES forKey:KEventLoggerEventNotificationSettingsChanged];
        [storage synchronize];

        if (settings.authorizationStatus != UNAuthorizationStatusAuthorized) {
            // Notifications not allowed
            NSLog(@"notification settings were changed");
            item.eventDescription = KEventLoggerEventNotificationsNotAllowed;

            // check settings for alert and sound
        }
       // UNNotificationSetting alertSetting = settings.alertSetting;
            if(settings.alertSetting == UNNotificationSettingEnabled){
                [storage setBool:YES forKey:@"alert permission granted"];
                item.eventDescription = KEventLoggerEventAlertsAreAllowed;
            }else{[storage setBool:NO forKey:@"alert permission granted"];
                item.eventDescription = KEventLoggerEventAlertsAreNotAllowed;
            }
            if (settings.soundSetting == UNNotificationSettingEnabled){
                [storage setBool:YES forKey:@"sound permission granted"];
                item.eventDescription = KEventLoggerEventSoundsAreAllowed;
            }else {[storage setBool:NO forKey:@"sound permission granted"];
                item.eventDescription = KEventLoggerEventSoundsAreNotAllowed;
            }

    }];
    NSLog(@"appdelegate - center didReceiveNotificationResponse");


    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];
        };
    }

视图控制器:

-(UNNotificationRequest *)triggerNotifications: (NSString *)identifier : (NSTimeInterval) interval{
// Note: identifier must be unique or else each new request causes all others to be cancelled.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"Timer expired", nil);
content.body = NSLocalizedString(@"Touch to continue", nil);
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
BOOL sound = [storage boolForKey:@"sound permission granted"];
if(sound){
    if([self.selectedSound isEqual:NSLocalizedString(kselectedSoundKeyDoorBell, nil)]){
        content.sound = [UNNotificationSound soundNamed:@"doorbell.caf"];
    }else if ([self.selectedSound isEqual:NSLocalizedString(kselectedSoundKeySystemDefault, nil)]){
        content.sound = [UNNotificationSound defaultSound];
    }else if ([self.selectedSound isEqual:NSLocalizedString(kselectedSoundKeyElectronicChime, nil)]){
        content.sound = [UNNotificationSound soundNamed:@"electronic_chime.caf"];
    }else{
        if([self.selectedSound isEqual:NSLocalizedString(kselectedSoundKeyComputer, nil)]){
            content.sound = [UNNotificationSound soundNamed:@"Computer.caf"];
        }
    }
}
content.categoryIdentifier = @"com.nelsoncapes.localNotification";
NSDate *today = [NSDate date];
NSDate *fireDate = [today dateByAddingTimeInterval:interval];
// first extract the various components of the date
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger year = [calendar component:NSCalendarUnitYear fromDate:fireDate];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:fireDate];
NSInteger day = [calendar component:NSCalendarUnitDay fromDate:fireDate];
NSInteger hour = [calendar component:NSCalendarUnitHour fromDate:fireDate];
NSInteger minute = [calendar component:NSCalendarUnitMinute fromDate:fireDate];
NSDateComponents *components = [[NSDateComponents alloc]init];
components.year = year;
components.month = month;
components.day = day;
components.hour = hour;
components.minute = minute;

// construct a calendarnotification trigger and add it to the system
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier: identifier content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError *error){
    if(error){
    NSLog(@"error on trigger notification %@", error);
    }
}];
}
4

1 回答 1

0

我相信我发现了问题(并且在我的代码中)。我使用相同的日期组件调用了 triggerNotification 两次(我只对分钟粒度感兴趣,因为我使用它在第 x 分钟触发警报)。第一次调用是在用户按下开始按钮时,第二次调用是在应用程序委托中调用 applicationDidBecomeActive 时。事实上,我确实在我的表格中看到了重复的通知。我认为,但不能表明,当系统有两个 UNNotificationRequests 等待相同的日期组件时,它只响应相应的警报横幅之一。所以,当我点击最新的横幅时,没有叫到代表。我删除了第二个触发器,问题似乎得到了解决(即,点击横幅中的按钮会导致呼叫我的代表)。笔记:

于 2018-06-13T22:48:55.483 回答