问题
I have a UILocalNotification that is supposed to fire once a day, Monday through Friday, but not on the weekend. I thought that setting the repeatInterval property of the notification to NSWeekdayCalendarUnit would accomplish this. Sadly for me, my notifications are still firing on the weekend. Can anyone suggest why? Here is my code:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = @"View";
localNotification.alertBody = NSLocalizedString(@"ALERT_MESSAGE", nil);
localNotification.soundName = UILocalNotificationDefaultSoundName;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM-dd-yyyy HH:mm"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/Toronto"]];
// Notification fire times are set by creating a notification whose fire date
// is an arbitrary weekday at the correct time, and having it repeat every weekday
NSDate *fireDate = [dateFormatter dateFromString:@"01-04-2012 11:00"];
localNotification.fireDate = fireDate;
localNotification.repeatInterval = NSWeekdayCalendarUnit;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
break;
[localNotification release];
回答1:
Weekday in iOS just means a day inside of a week. It doesn't have the "work week" connotation as opposed to a weekend.
The documentation says it a little clearer, by suggesting that you use 1-7 as the units:
NSWeekdayCalendarUnit
Specifies the weekday unit.
The corresponding value is an kCFCalendarUnitSecond. Equal to kCFCalendarUnitWeekday. The weekday units are the numbers 1 through N (where for the Gregorian calendar N=7 and 1 is Sunday).
Source: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/Reference/NSCalendar.html
To properly set your notifications from Monday through Friday, here's some skeleton code. Yo'll have to execute it 5 times, so it'd be good to encapsulate it inside of a method that parameters for the fireDate. I've shown how you could do it for Monday.
UILocalNotification *notification = [[[UILocalNotification alloc] init] autorelease];
// Set this to an NSDate that is for the time you want, on Monday
notification.fireDate = fireDate;
// Repeat every week
notification.repeatInterval = NSWeekCalendarUnit;
回答2:
You have to set day separately for local notification and set local Notification repeatInterval to NSWeekCalendar Unit. AS
[self notificationWithItem:tempDict Date:[self SetDateForAlarmWithWeekday:2 :tempDict] andRepeatInterval:NSWeekCalendarUnit];
[self notificationWithItem:tempDict Date:[self SetDateForAlarmWithWeekday:3 :tempDict]andRepeatInterval:NSWeekCalendarUnit];
[self notificationWithItem:tempDict Date:[self SetDateForAlarmWithWeekday:4 :tempDict] andRepeatInterval:NSWeekCalendarUnit];
[self notificationWithItem:tempDict Date:[self SetDateForAlarmWithWeekday:5 :tempDict] andRepeatInterval:NSWeekCalendarUnit];
[self notificationWithItem:tempDict Date:[self SetDateForAlarmWithWeekday:6 :tempDict] andRepeatInterval:NSWeekCalendarUnit];
Here I have made the methods setDateForAlarmWithWeekday that returns date to be setted in fireDate property of local Notification and notificationWithItem that sets Local Notification.
-(void) notificationWithItem:(NSDictionary*)tmpdict Date:(NSDate *)date andRepeatInterval:(NSCalendarUnit)CalUnit
{
UILocalNotification *localNotification =[[UILocalNotification alloc]init];
if (localNotification==nil) {
return;
}
localNotification.fireDate=date;
localNotification.timeZone=[NSTimeZone defaultTimeZone];
localNotification.repeatCalendar=[NSCalendar currentCalendar];
localNotification.alertBody=[NSString stringWithFormat:@"%@",[tmpdict objectForKey:@"Reminder"]];
NSDictionary *snoozeDic=[tmpdict objectForKey:@"Snooze"];
if ([[snoozeDic valueForKey:@"Switch"]intValue]==1) {
localNotification.alertAction=@"Snooze";
}else
{
localNotification.hasAction=NO;
}
localNotification.repeatInterval=CalUnit;
localNotification.soundName=[NSString stringWithFormat:@"%@.caf",[tmpdict objectForKey:@"Tone"]];
localNotification.userInfo=[NSDictionary dictionaryWithObject:tmpdict forKey:@"AlarmInfo"];
localNotification.applicationIconBadgeNumber=1;
[[UIApplication sharedApplication]scheduleLocalNotification:localNotification];
}
-(NSDate*)SetDateForAlarmWithWeekday:(int)WeekDay:(NSDictionary*)dics
{
NSLog(@"set date for alarm called");
NSCalendar *calendar=[NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone defaultTimeZone]];
unsigned currentFlag=NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit|NSWeekdayCalendarUnit;
NSDateComponents *comp=[calendar components:currentFlag fromDate:[NSDate date]];
NSArray *array=[[dics objectForKey:@"Time"] componentsSeparatedByString:@" "];
NSInteger hour=[[[[array objectAtIndex:0] componentsSeparatedByString:@":"] objectAtIndex:0] intValue];
NSInteger min=[[[[array objectAtIndex:0] componentsSeparatedByString:@":"] objectAtIndex:1] intValue];
if ([[array objectAtIndex:1] isEqualToString:@"PM"]) {
hour=hour+12;
}
else
{
if (hour==12) {
hour=0;
}
}
comp.hour=hour;
comp.minute=min;
comp.second=0;
NSLog(@"set date for alarm (%i:%i:%i)",comp.hour,comp.minute,comp.second);
NSLog(@"weekday :%i ",WeekDay);
NSLog(@"comp weekday %i",comp.weekday);
int diff=(WeekDay-comp.weekday);
NSLog(@"difference :%i",diff);
int multiplier;
if (WeekDay==0) {
multiplier=0;
}else
{
multiplier=diff>0?diff:(diff==0?diff:diff+7);
}
NSLog(@"multiplier :%i",multiplier);
return [[calendar dateFromComponents:comp]dateByAddingTimeInterval:multiplier*secondsInOneDay];
}
I hope this will help u.
回答3:
I have also searched about it. Below code work good for me. Pass the week day value 1 to 7 Sunday to Saturday and notification body with action which you want to fire and specify your date then notification will come on that specific day. For weekends call this function twice with value 7 and 1 for Saturday and Sunday.
Hope this help you.
- (void) weekEndNotificationOnWeekday: (int)weekday :(UILocalNotification *)notification : (NSDate*) alramDate
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: alramDate];
[componentsForFireDate setWeekday: weekday] ; //for fixing Sunday
// [componentsForFireDate setHour: 20] ; //for fixing 8PM hour
// [componentsForFireDate setMinute:0] ;
// [componentsForFireDate setSecond:0] ;
notification.repeatInterval = NSWeekCalendarUnit;
notification.fireDate=[calendar dateFromComponents:componentsForFireDate];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
回答4:
Similar but in Swift.
Remember that WeekDay starts at 1 = Sunday and goes to 7. See Apple Docs: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/
func scheduleLocalNotification(date:NSDate, weekDay:Int){
guard let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian),
let groupName = dateFormatter?.stringFromDate(date) else { return }
calendar.timeZone = NSTimeZone.defaultTimeZone()
let dateComponents = NSDateComponents()
dateComponents.calendar = calendar
dateComponents.hour = calendar.component(.Hour, fromDate: date)
dateComponents.minute = calendar.component(.Minute, fromDate: date)
dateComponents.weekOfYear = calendar.component(.WeekOfYear, fromDate: date)
dateComponents.weekday = weekDay
let localNotificaion = UILocalNotification()
localNotificaion.fireDate = calendar.dateFromComponents(dateComponents)
localNotificaion.alertBody = "Hey!"
localNotificaion.timeZone = NSTimeZone.defaultTimeZone()
localNotificaion.userInfo = ["Time": groupName]
localNotificaion.repeatInterval = .WeekOfYear
UIApplication.sharedApplication().scheduleLocalNotification(localNotificaion)
}
来源:https://stackoverflow.com/questions/9855147/uilocalnotification-is-supposed-to-repeat-every-weekday-but-fires-on-weekends-a