【问题标题】:Scheduled local notifications are irregular预定的本地通知不定期
【发布时间】:2017-11-05 02:57:12
【问题描述】:

我的 iOS 本地通知遇到了严重问题。我有一个用 Objective-C 编写的应用程序,它允许用户选择通知触发的时间以及一周中的哪几天(它应该每周在指定时间的指定日期触发)。我对通知触发的时间没有任何问题,它可以正常工作。但是,当我指定它应该触发的日期时,会发生奇怪的事情。起初,它们会开火一次,但每天都开火,而不是只在指定的日子开火。然后,在第一周之后,他们每天都开火,但不止一次。相反,它们触发的次数与指定的日期一样多(因此,如果选择了星期日、星期一和星期二,则用户每天将在指定时间收到 3 个连续通知)。

这是我用来设置通知的代码。

点击“保存”按钮后,首先会清除所有通知,为新通知让路。

//cancels all notifications upon save
[[UIApplication sharedApplication] cancelAllLocalNotifications];

接下来,我使用 NSDate、NSCalendar 和 NSCalendarComponents 来获取当前时间的详细信息,以及我的 UIPicker(用于选择一天中的时间)中的组件

NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitWeekOfYear|NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute fromDate:now];//get the required calendar units


然后,我从 UIPicker 中获取时间单位,以及从选取器中获取实际时间的单位。

NSDateComponents *pickedComponents = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:picker.date];
NSDate *minuteHour = [calendar dateFromComponents:pickedComponents];
[[NSUserDefaults standardUserDefaults] setObject:minuteHour forKey:@"FireTime"];


之后,我设置了我想在通知中显示的文本

NSString *reminder = @"Reminder text!";

接下来是通知的实际设置。它们都是一样的(当然是星期几变了),所以我只显示星期天的那个。

//sunday
UILocalNotification *localNotificationSunday = [[UILocalNotification alloc] init];
if ([sundayTempStatus isEqual:@"1"])
{

    //permanently save the status
    [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"Sunday"];

    //set up notifications
    //if it is past sunday, push next week
    if (components.weekday > 1)
    {
        components.day = components.day + 7; //if already passed sunday, make it next sunday
    }

    //components.day = 1;
    components.hour = [pickedComponents hour];
    components.minute = [pickedComponents minute];

    NSDate *fireDate = [calendar dateFromComponents:components];

    localNotificationSunday.fireDate = fireDate;
    localNotificationSunday.alertBody = reminder;
    localNotificationSunday.timeZone = [NSTimeZone systemTimeZone];
    localNotificationSunday.repeatInterval = NSCalendarUnitWeekOfYear;
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotificationSunday];
}
else
{
    [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"Sunday"];
}


非常感谢任何帮助,如果需要任何其他信息或代码,我很乐意提供。

【问题讨论】:

    标签: ios objective-c notifications nsdate uilocalnotification


    【解决方案1】:

    当代码变得重复时,它通常变得更容易出错。我写了一个简单的方法来处理提醒的时间安排。

    - (void)scheduleNotificationForDayOfWeek:(int)dayOfWeek withPickedComponents:(NSDateComponents *)pickedComponents andReminderString:(NSString *)reminderString {
        NSCalendar *calendar = [NSCalendar currentCalendar];
        UILocalNotification *notification = [[UILocalNotification alloc] init];
    
        NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitWeekOfYear|NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute fromDate:[NSDate date]];
        components.hour = [pickedComponents hour];
        components.minute = [pickedComponents minute];
    
        NSDateComponents *additionalComponents = [[NSDateComponents alloc] init]; // to be added onto our date
        if ([components weekday] < dayOfWeek) {
            additionalComponents.day = (dayOfWeek - [components weekday]); // add the number of days until the next occurance of this weekday
        } else if ([components weekday] > dayOfWeek) {
            additionalComponents.day = (dayOfWeek - [components weekday] + 7); // add the number of days until the next occurance of this weekday
        }
    
        NSDate *fireDate = [calendar dateFromComponents:components];
        fireDate = [calendar dateByAddingComponents:additionalComponents toDate:fireDate options:0]; // add on our days
    
        notification.fireDate = fireDate;
        notification.alertBody = reminderString;
        notification.timeZone = [NSTimeZone systemTimeZone];
        notification.repeatInterval = NSCalendarUnitWeekOfYear;
        [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    }
    

    这实际上非常简单。用一周中的某一天调用它(例如,0 = 星期日,1 = 星期一),它会为那一天安排一个重复的提醒。我无法在我的测试中用你的周日代码重现你的问题,所以我认为在重复该代码的某个地方你一定犯了一个错误。

    在这种方法中,火灾日期的获取得到了简化。它使用 NSDateComponents 轻松获取该工作日的下一个事件。像这样称呼它:[self scheduleNotificationForDayOfWeek:0 withPickedComponents:pickedComponents andReminderString:@"Hello, world!"];(每周日在指定组件处显示“Hello, world!”)

    使用这个 sn-p,您应该能够摆脱代码中的大部分重复语句,并简化设置通知的方式。对我来说,这非常有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多