2017-06-04 33 views
0

我在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"]; 
} 


任何幫助是極大的讚賞,以及如果需要任何額外的信息或代碼,我會很樂意提供。

回答

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!」)

使用此代碼段,您應該能夠擺脫代碼中的大部分重複語句,並簡化如何設置通知。對我而言,這個工作很完美。