How to set multiple UILocalNotifications - ios

In my app I am using UILocalNotifications. I want to set notifications for different days of the week.For that, I have different dates in an array. But I am getting wrong results. Is there anything wrong with my code. My code is
for(int counter=0 ;counter<[daysArray count]; counter++)
{
int day = [[daysArray objectAtIndex:counter] intValue];
NSDate *specificDate = [self getDateOfSpecificDay:day];
UILocalNotification *localNotification = [[UILocalNotification alloc]init];
localNotification.fireDate = specificDate;
localNotification.repeatInterval = NSWeekdayCalendarUnit;
localNotification.soundName = sound;
localNotification.alertBody = [NSString stringWithFormat:#"%#",specificDate];
localNotification.alertAction = #"Show me the item";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
NSLog(#"%#",localNotification);
}

we have done something similiar to your question but i dont know it will help you or not..just try this **NSWeekdayCalendarUnit**i suggest you just refer my answer.
NSCalendar *gregCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponent = [gregCalendar components:NSYearCalendarUnit|NSWeekCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:[NSDate date]];
NSArray *dobArray = [NSArray arrayWithObjects:#"02-08-2014", #"10-08-2014", #"14-08-2014", #"15-08-2014", #"16-08-2014", #"17-08-2014", #"18-08-2014", #"22-08-2014", #"28-08-2014", #"29-08-2014",nil];
NSArray *messagesArray = [NSArray arrayWithObjects:#"Literacy And Numeracy workshop for parents and children", #"raksha Bandhan", #"Tri Colour Dat(School celebration)", #"Independence day (School Holiday)", #"PTM/Book Exhibition", #"Janmastami", #"Parsi New Year- School Holiday", #"Clown Day", #"Eco Friendly Ganesha-School Holiday", #"Ganesh Chaturthi-School Holiday",nil];
for (NSString *dobStr in dobArray)
{
NSArray *components = [dobStr componentsSeparatedByString:#"-"];
if(components.count>2) {
NSInteger aDay = [[components objectAtIndex:0] integerValue];
NSInteger aMonth = [[components objectAtIndex:1] integerValue];
// NSInteger aYear = [[components objectAtIndex:2] integerValue];
if(aDay == [dateComponent day] && aMonth == [dateComponent month]) { // dob is here
[dateComponent setDay:aDay];
[dateComponent setMonth:aMonth];
[dateComponent setYear:[dateComponent year]];
[dateComponent setHour:16];
[dateComponent setMinute:54];
UIDatePicker *dp = [[UIDatePicker alloc] init];
[dp setDate:[gregCalendar dateFromComponents: dateComponent]];
UILocalNotification *notification = [[UILocalNotification alloc] init];
NSInteger index = [dobArray indexOfObject:dobStr];
// [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:10]];
[notification setAlertBody:[messagesArray objectAtIndex:index]];
[notification setFireDate:dp.date];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[application setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
return YES;
}
}
}

I Think here you are misusing the line localNotification.repeatInterval = NSWeekdayCalendarUnit;
it will let your notification repeat every day of week that is creating problem in your case. Please remove this line and try again it will work.

Related

Why my notification is being scheduled 5 hours earlier

I am making an app where I have to schedule local notifications for all the time stamps that is stored in my database when the app will be installed for the first time.
The notifications are being scheduled but when the alarm rings, I realize it is ringing at a time that is exactly 5 hours delayed than the current time. Imagine, I have 3 notifications to go off today- one at 2:11 pm, another at 3:18 pm and another at 8:15 pm. Now, imagine my current time is 7:11pm. I will have a notification go off. which is exactly 5 hours after my first timestamp. Then again it is go off at 8:18 pm.
The following is my code. Can anyone please help.
-(void) setLocalNotification {
TimeCalculationLogic *timeManager = [[TimeCalculationLogic alloc]init];
NSMutableArray *allTimeStamps = [timeManager getAllTimeStamps];
NSDate *currentTime;
for(beginningTime *time in allTimeStamps){
NSDate *currentDate = [timeManager getDateFromString:time.activeDate];
currentTime = [timeManager getDateTimestampFromString:time.first];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
currentTime = [timeManager getDateTimestampFromString:time.second];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
currentTime = [timeManager getDateTimestampFromString:time.third];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
}
NSArray *activeNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// Add back the still relevant notifications
for (UILocalNotification *notification in activeNotifications) {
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
-(void)getComponentToScheduleNotificationFromDate:(NSDate*)date andTime:(NSDate*)timestamp{
self.schedulerComponent = [[NSDateComponents alloc] init];
NSCalendar *calender = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
NSDateComponents *components;
components = [calender components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[self.schedulerComponent setYear:year];
[self.schedulerComponent setMonth:month];
[self.schedulerComponent setDay:day];
components = [calender components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:timestamp];
NSInteger hour = [components hour];
NSInteger minute = [components minute];
NSInteger second = [components second];
[self.schedulerComponent setHour:hour];
[self.schedulerComponent setMinute:minute];
[self.schedulerComponent setSecond:second];
[self.schedulerComponent setTimeZone:[NSTimeZone systemTimeZone]];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
NSDate *setTime = [cal dateFromComponents:self.schedulerComponent];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = setTime;
localNotif.timeZone = [NSTimeZone systemTimeZone];
localNotif.alertBody = #"It's time Again!";
localNotif.alertAction = #"View";
localNotif.soundName = #"ajan.caf";
localNotif.applicationIconBadgeNumber = 1;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}

UILocalNotification repeatInterval on 20 days

I'd like to create local notification with custom interval repeat (every 20 days for example).
I know we have NSDayCalendarUnit, kCFCalendarUnitMonth ... but I hope to set repeat interval at 20 days.
I don't want to create a notification for every day.
My real need is to repeat a notification for consecutive 21 days, then don't launch it for 7 days later, then a new 21 days with notification and 7 days without ... etc.
I should schedule all these days even if application is inactive.
To do this I decide to create a 21 notifications since a fire date with repeatInterval = 28days (here is the problem)
Try this, you can change the intervall by selecting setDay, setMonth, .... :
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:3];
NSDate *date3Days = [calendar dateByAddingComponents:components
toDate:[NSDate date]
options:0];
UIApplication* app = [UIApplication sharedApplication];
NSArray* oldNotifications = [app scheduledLocalNotifications];
if ( oldNotifications ) {
[app cancelAllLocalNotifications];
app.applicationIconBadgeNumber = 0;
}
UILocalNotification* notifyAlarm = [[UILocalNotification alloc] init];
if (notifyAlarm) {
notifyAlarm.fireDate = date3Days;
notifyAlarm.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm.alertBody = NSLocalizedString( #"Push message", #"");
notifyAlarm.soundName = #"sound.wav";
[app scheduleLocalNotification:notifyAlarm];
}
If you want to set a specific time after which the UILocalNotifications should appear you can create a method of the above solution and loop over an array which indicates the days you like to show a notification:
NSArray *arrayNumbers = #[#5, #7, #14, #21, #30, #60, #90, #120];
NSDictionary *dictNotifications =
[[NSUserDefaults standardUserDefaults] objectForKey:kUserDefAppStarts];
for ( NSNumber *bla in arrayNumbers ){
NSString *strKey = [NSString stringWithFormat:#"%#%#", kUserDefAppStarts, bla];
NSDictionary *dict = dictNotifications[strKey];
NSString *strMessageQuestion = dict[kKeyMessage];
[self createNotificationWithNumberOfDays:[bla integerValue]
andMessage:strMessageQuestion
userInfo:dict];
}
And here is the method you have to call
+ (void)createNotificationWithNumberOfDays:(int)days
andMessage:(NSString *)message
userInfo:(NSDictionary *)dict{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:days];
NSDate *dateAlert = [gregorian dateByAddingComponents:components toDate:[NSDate date] options:0];
UIApplication *app = [UIApplication sharedApplication];
UILocalNotification *notifyAlarm = [[UILocalNotification alloc] init];
if( notifyAlarm ){
[notifyAlarm setFireDate:dateAlert];
[notifyAlarm setTimeZone:[NSTimeZone defaultTimeZone]];
[notifyAlarm setSoundName:#"soundname"];
[notifyAlarm setAlertBody:message];
[notifyAlarm setUserInfo:dict];
[app scheduleLocalNotification:notifyAlarm];
}
}
If you wanted to schedule a UILocalNotification for 20 days in the future from the current time you would do this:
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *dateComp = [[NSDateComponents alloc] init];
int desiredAmountOfMonths = 4;
for (int month = 0; month < desiredAmountOfMonths; month++)
{
dateComp.month = month;
dateComp.day = 20;
NSDate *fireDate = [currentCalendar dateByAddingComponents:dateComp toDate:[NSDate date] options:NSCalendarMatchNextTimePreservingSmallerUnits];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = fireDate;
notification.timeZone = [NSTimeZone defaultTimeZone];
}
You will need to modify the UILocalNotification for what message, sound, etc and then fire the notification once done customizing.

ios. Disable everyday notification if it is already irrelevant

I want to remind user to take photo everyday. I use code for every day local push notificatons
UILocalNotification *everyDayNotification = [[UILocalNotification alloc] init];
everyDayNotification.repeatInterval = NSDayCalendarUnit;
NSDate *currentDate = [[NSDate alloc] init];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate];
int hour = [hours_string intValue];
int minutes = [minutes_string intValue];
[components setHour:hour];
[components setMinute:minutes];
NSDate *today10am = [calendar dateFromComponents:components];
everyDayNotification.fireDate = today10am;
everyDayNotification.timeZone = [NSTimeZone defaultTimeZone];
everyDayNotification.alertBody = #"It us time";
everyDayNotification.alertAction = #"Action";
everyDayNotification.soundName = UILocalNotificationDefaultSoundName;
everyDayNotification.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"EveryDay"
forKey:#"RemindNotificaion"];
everyDayNotification.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:everyDayNotification];
But if the user has made the photo before it is time to notice that. I want to skip the notification for today. Is that possible?
I would suggest making an individual UILocalNotification for each day and storing them, perhaps in an array in NSUserDefaults. Then you can cancel a notification with the following:
[[UIApplication sharedApplication] cancelLocalNotification:notficiationInstance];

Store multiple UILocalNotification in UserInfo

this is how i setting my local notification, all work well.
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:[_datePicker date]];
NSLog(#"%#",[_datePicker date]);
NSDate *fireDate = [gregorianCalendar dateFromComponents:components];
NSLog(#"Fire date : %#",fireDate);
// check if the time is already passed
if ([fireDate compare:[NSDate date]] == NSOrderedAscending)
{
// if it does add 1 day
components.day = components.day+1;
fireDate = [gregorianCalendar dateFromComponents:components];
}
NSLog(#"Fire date : %#",fireDate);
for (int i = 0; i < 7; i++) {
NSDate *scheduleDate = [fireDate dateByAddingTimeInterval:(i * 24.0f * 3600.0f)];
NSDateComponents *componentsForEachDay = [gregorianCalendar components:NSWeekdayCalendarUnit fromDate:scheduleDate];
if (componentsForEachDay.weekday != 7) { // To skip Saturday
localNotification = [[UILocalNotification alloc] init];
localNotification.repeatInterval = NSWeekCalendarUnit;
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertBody = #"test";
localNotification.repeatInterval = NSCalendarUnitDay;
localNotification.applicationIconBadgeNumber = 0;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"%i",i] forKey:[NSString stringWithFormat:#"bracletNotif%i",i]];
localNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
i always get only the last object in userInfo.. how can i store all the scheduleLocalNotification in the userInfo for later cancel?
how does its work? before every scheduleLocalNotification i need so save an object and key? or can i save them all at one?
because i already tried to do that, i got all the userInfo objects but could not delete them :/
SOS please.
If you are trying to cancel all braclet notifications instead of giving them all a different key/value you could do this instead:
localNotification.userInfo = #{#"category": #"bracelet"};
To cancel:
[[[UIApplication sharedApplication] scheduledLocalNotifications] enumerateObjectsUsingBlock:^(UILocalNotification *notification, NSUInteger idx, BOOL *stop) {
NSDictionary *userInfo;
if((userInfo = [notification userInfo])){
NSString *categoryValue;
if((categoryValue = [userInfo objectForKey:#"category"]) && [categoryValue isEqualToString:#"bracelet"]){
[[UIApplication sharedApplication] cancelLocalNotification: notification];
}
}
}];
What we are doing here is grouping all notifications into the category: bracelet. I have chosen the key category due to future changes in the sdk. We could schedule more notifications e.g. category: neckless
Then when required we loop through all the UILocalNotifications and scan for the category key in the notifications userInfo, in the example above if the keys value equals bracelet, then we cancel the notification.
if((categoryValue = [userInfo objectForKey:#"category"]) && [categoryValue isEqualToString:#"bracelet"]){
This line of code is checking whether a key of category exists (i.e. not nil) whilst assigning it to the variable categoryValue then the if statement is immediately checking if the categoryValue is equal to bracelet
It could have been rewritten as:
NSString *categoryValue = [userInfo objectForKey:#"category"];
if(categoryValue && [categoryValue isEqualToString:#"bracelet"]){

Notification in iphone app

I have read many post of notification but somehow i am going wrong somewhere so that's why i post this question. I want to get daily notification at 9.00 am in my app. I get it properly at 9.00 am with no problem what so ever but the difficulty is that i also get same notification at 2.00 am. I try with following code. Can anyone tell me where i am getting wrong. Or is it problem of ios6. Any kind of help will be appreciated. Thank you.
NSString *day =#"9:00 AM";
NSDateFormatter *dateFormat = [[[NSDateFormatter alloc] init]autorelease];
[dateFormat setDateFormat:#"hh:mm a"];
//NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
//[dateFormat setTimeZone:gmt];
NSDate *today=[dateFormat dateFromString:day];
NSLog(#"string %# & date %#",day,today);
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil)
{
// delObj.QCouter=delObj.QCouter+1;
//[[UIApplication sharedApplication] cancelAllLocalNotifications];
notif = [[cls alloc] init];
notif.fireDate =today;
notif.timeZone = [NSTimeZone systemTimeZone];
NSLog(#"timeZone %# ",[NSTimeZone systemTimeZone]);
notif.alertBody = #"You have a new letter ";
notif.alertAction = NSLocalizedString(#"View", nil);;
notif.soundName = #"Ding3.wav";
notif.applicationIconBadgeNumber = 1;
notif.repeatInterval = NSDayCalendarUnit;
[[NSUserDefaults standardUserDefaults] setObject:#"1" forKey:#"Status"];
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"You have a notifiaction"
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
// NSLog(#"userInfo %#",notif.userInfo);
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
[[NSUserDefaults standardUserDefaults] setObject:#"CurrentDay" forKey:#"DayChange"];
}
Hi try following code:-
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDate *date = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *components = [gregorian components: NSUIntegerMax fromDate: date];
[components setHour: 9];
[components setMinute: 0];
[components setSecond: 0];
NSDate *today = [gregorian dateFromComponents: components];
[gregorian release];
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil)
{
notif = [[cls alloc] init];
notif.fireDate =today;
notif.alertBody = #"You have a new letter ";
notif.alertAction = NSLocalizedString(#"View", nil);;
notif.soundName = #"Ding3.wav";
notif.applicationIconBadgeNumber = 1;
notif.repeatInterval = NSDayCalendarUnit;
[[NSUserDefaults standardUserDefaults] setObject:#"1" forKey:#"Status"];
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"You have a notifiaction"
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
// NSLog(#"userInfo %#",notif.userInfo);
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
[[NSUserDefaults standardUserDefaults] setObject:#"CurrentDay" forKey:#"DayChange"];
}
Simulator or real device?
Simulator has a known bug where it generates two "fires" of a single notification. If that's what's happening, try it on a physical device and see if the same behavior occurs. It's annoying, but not an actual problem with your app. (Assuming it's the simulator, of course!)
See this question: iOS – UILocalNotification fired twice for same notification
Edit based on "not in the simulator":
try adding a call to this after you schedule the notification, and see if some other part of your code is slipping in another scheduled item you're not aware of:
- (void) _debug_logExistingToConsole
{
if (LOG) NSLog(#"Notifications set is now: \n");
UIApplication *Ap = [UIApplication sharedApplication];
NSArray* arr = [Ap scheduledLocalNotifications];
if (LOG) NSLog(#"%#", arr);
}

Resources