iOS UILocalNotification 设置为每天触发一次,每两天触发一次,并且仅在星期日触发

Posted

技术标签:

【中文标题】iOS UILocalNotification 设置为每天触发一次,每两天触发一次,并且仅在星期日触发【英文标题】:iOS UILocalNotification set to fire once every day, once every two days, and only on Sundays 【发布时间】:2013-10-31 10:56:38 【问题描述】:

我正在尝试使用设置包来安排 UILocalNotification。在设置中,您可以选择是否希望每天(每天 1 次)、每 2 天 1 次、仅在周日或从不发送通知。

这是我使用的代码(全部在 AppDelegate.m 中):

    -(void)defaultsChanged:(NSNotification *)notification 

         [[UIApplication sharedApplication] cancelAllLocalNotifications];

        [[NSUserDefaults standardUserDefaults]synchronize];
        NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:@"multi_preference"];

        NSLog(@"%@", testValue);

        NSDate *today = [NSDate date];

        NSCalendar* calendar = [NSCalendar currentCalendar];
        NSDateComponents* compoNents = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:today]; // Get necessary date components

        [compoNents month];[compoNents day];

        NSDictionary *dictToday= [self getDataFromdate : [compoNents day] month:[compoNents month]];


        if ([testValue isEqualToString:@"one"])
            UILocalNotification* localNotification = [[UILocalNotification alloc] init];
            localNotification.fireDate = [[NSDate date]dateByAddingTimeInterval:20];
            localNotification.alertAction = @"View";
            localNotification.alertBody = [dictToday objectForKey:@"saint_description"];
            localNotification.repeatInterval = NSDayCalendarUnit;
            localNotification.timeZone = [NSTimeZone defaultTimeZone];
            localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
             [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];

             
        if (testValue==Nil)
            UILocalNotification* localNotification = [[UILocalNotification alloc] init];
            localNotification.fireDate = [[NSDate date]dateByAddingTimeInterval:20];
            localNotification.alertAction = @"View";
            localNotification.alertBody = [dictToday objectForKey:@"saint_description"];
            localNotification.repeatInterval = NSDayCalendarUnit;
            localNotification.timeZone = [NSTimeZone defaultTimeZone];
            localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];

        
        if ([testValue isEqualToString:@"two"])

            UILocalNotification* localNotification = [[UILocalNotification alloc] init];
            localNotification.fireDate = [[NSDate date]dateByAddingTimeInterval:86401];
            localNotification.alertAction = @"View";
            localNotification.alertBody = [dictToday objectForKey:@"saint_description"];
            localNotification.repeatInterval = NSDayCalendarUnit;
            localNotification.timeZone = [NSTimeZone defaultTimeZone];
            localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
             [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];

        

        if ([testValue isEqualToString:@"three"])
        NSDate *today2 = [[NSDate alloc] init];
        NSCalendar *gregorian = [[NSCalendar alloc]
                                 initWithCalendarIdentifier:NSGregorianCalendar];

        // Get the weekday component of the current date
        NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit
                                                           fromDate:today2];

        /*
         Create a date components to represent the number of days to subtract from the current date.
         The weekday value for Sunday in the Gregorian calendar is 1, so subtract 1 from the number of days to subtract from the date in question.  (If today is Sunday, subtract 0 days.)
         */
        NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
        [componentsToSubtract setDay: 0 - ([weekdayComponents weekday] - 1)];

        NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract
                                                             toDate:today2 options:0];

        /*
         Optional step:
         beginningOfWeek now has the same hour, minute, and second as the original date (today).
         To normalize to midnight, extract the year, month, and day components and create a new date from those components.
         */
        NSDateComponents *components =
        [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit |
                               NSDayCalendarUnit) fromDate: beginningOfWeek];
        beginningOfWeek = [gregorian dateFromComponents:components];



            UILocalNotification* localNotification = [[UILocalNotification alloc] init];
            localNotification.fireDate = beginningOfWeek;
            localNotification.alertAction = @"View";
            localNotification.alertBody = [dictToday objectForKey:@"saint_description"];
            localNotification.repeatInterval = NSWeekdayCalendarUnit;
            localNotification.timeZone = [NSTimeZone defaultTimeZone];
            localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];

        
    

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions


    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(defaultsChanged:)
                                                 name:NSUserDefaultsDidChangeNotification
                                               object:nil];

    UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (locationNotification) 
        // Set icon badge number to zero
        application.applicationIconBadgeNumber = 0;
    
return yes;

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification





    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Today's Saint"
                                                    message:notification.alertBody
                                                   delegate:self cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    if (notification.alertBody!=Nil)
    [alert show];


     [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];

    // Set icon badge number to zero
    application.applicationIconBadgeNumber = 0;

如我所说,启动通知的代码是否正确? 如果不是,它有什么问题?谢谢!

【问题讨论】:

【参考方案1】:

您似乎正在安排用户更改偏好时的通知。但是,您永远不会取消安排之前安排的通知,这就是为什么您观察到的通知突发的时间与您一天或两天前反复更改设置的时间完全一致。

您安排的通知与您打算修改的通知集是不同的对象。不幸的是,UILocalNotifications 没有标识符标记。

但是,只要您收到带有[[UIApplication sharedApplication] cancelAllLocalNotifications];defaultsChanged: 消息,在重新安排之前,您就可以取消安排之前的所有通知。这将解决您的问题。

还请仔细查看 this solution,它建议即使在启动时也取消和重新安排通知,以避免在用户重新安装您的应用时出现突发或重复通知。

【讨论】:

谢谢,我已经在使用cancelAllLocalNotifications方法了,但是不知道为什么,忘记贴在这里了。问题是,现在他们没有在应该启动的时候启动。例如,如果我使用 localNotification.fireDate = [[NSDate date]dateByAddingTimeInterval:20];和 localNotification.repeatInterval=NSDayCalendarUnit;它会在每天 20 秒后每天发布通知吗? 也许你在错误的地方使用它? cancelAllLocalNotifications 应该是你在粘贴的方法中做的第一件事。 我已经更新了代码。但是通知只是没有在应该启动的时候启动。有什么想法吗? 另外,除了重新调度方法之外,其他任何地方都没有cancelAllLocalNitifications【参考方案2】:

我有两个想法,

首先:dictToday 的价值是什么?

NSDictionary *dictToday= [self getDataFromdate : [compoNents day] month:[compoNents month]];
[dictToday objectForKey:@"saint_description"]

如果此值为 nil,则不会弹出通知。

第二:检查你的时区和返回的时区:

[NSTimeZone defaultTimeZone]

您可能处于 +3 时区并将本地通知设置为在负时区触发,而这永远不会发生。

【讨论】:

以上是关于iOS UILocalNotification 设置为每天触发一次,每两天触发一次,并且仅在星期日触发的主要内容,如果未能解决你的问题,请参考以下文章

iOS8 - UILocalNotification,稍后从代码中检查权限

iOS的本地推送UILocalNotification的使用

iOS开发---本地通知(UILocalNotification)

UILocalNotification 在 iOS11 中不起作用

iOS 的 UILocalNotification 中不显示操作和类别

iOS9 的 UILocalNotification 问题