I'm trying to use a settings bundle to schedule a UILocalNotification. In settings, you can choose if you want the notifications to come daily (1/day), 1 every 2 days, only on Sundays or never.
Here is the code I used (this is all in 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;
}
Is the code correct for launching the notifications as I've stated? If not, what's the problem with it? Thanks!
It seems you are scheduling notifications whenever the user changes preferences. However, you never unschedule previously scheduled notifications, which is why you are observing bursts of notifications at times that will correspond exactly to the times you repeatedly changed settings a day or two days ago.
The notifications you schedule are different objects than the set of notifications that you intend to modify. Unfortunately, UILocalNotifications
have no identifier tokens.
However, you can unschedule all previous notifications whenever you receive a defaultsChanged:
message with [[UIApplication sharedApplication] cancelAllLocalNotifications];
before you reschedule. This will solve your problem.
Also have a close look at this solution which suggests to cancel and reschedule notifications even upon launch to avoid bursts or duplicate notifications when a user re-installs your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With