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"]){
Related
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.
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];
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);
}
- (void)scheduleNotification :(int) rowNo
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.timeZone = [NSTimeZone defaultTimeZone];
NSString *descriptionBody=[[remedyArray objectAtIndex:rowNo]objectForKey:#"RemedyTxtDic"];
NSLog(#"%#",descriptionBody);
notif.alertBody = [NSString stringWithString:descriptionBody];
notif.alertAction = #"Show me";
notif.soundName = UILocalNotificationDefaultSoundName;
notif.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:notif.alertBody
forKey:#"kRemindMeNotificationDataKey"];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
}
I have a column name frequency which is fetched from Sqldb where it contains the number of times notification should appear for a particular cell.
if frequency = 3 ..the notification should fire say 8 AM , 2PM then 8PM
if frequency = 4 ..the notification should fire say 8 AM , 12PM , 4PM then 8PM.
Is there a way to do it? If anyone can help me that would be great
Unfortunately, You can specify value for repeatInterval only of type NSCalendarUnit (day, week, month). So, I think, You need to create several Notifications with different fireDate, and specify for them repeatInterval = NSDayCalendarUnit
For example,
NSDate *currentTime = [NSDate date];
notification1.fireDate = [NSDate dateWithTimeInterval:SOME_INTERVAL sinceDate:currentTime];
notification1.repeatInterval = NSDayCalendarUnit;
notification2.fireDate = [NSDate dateWithTimeInterval:SOME_INTERVAL * 2 sinceDate:currentTime];
notification2.repeatInterval = NSDayCalendarUnit;
After user viewed some of notifications - You can cancel them.
Update.
You can also create NSDate from different components like this:
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setWeekday:2]; // Monday
[components setWeekdayOrdinal:1]; // The first Monday in the month
[components setMonth:5]; // May
[components setYear:2013];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:components];
Also You can set hour, minutes, seconds, timezone and other parameters.
I am working on a application that reminds about the expiry date. I have implemented the same using UILocalNotification with repeat Interval (NSMonthCalendarUnit, NSDayCalendarUnit,NSDayCalendarUnit). For example I have the fire date on 01-01-2012 and the repeat interval is NSDayCalendarUnit and the end date is 12-12-2012, is it possbile to cancelLocalNotification: on expiry.
here is the code:-
- (void) scheduleNotificationOn:(NSDate*) fireDate
text:(NSString*) alertText
action:(NSString*) alertAction
sound:(NSString*) soundfileName
launchImage:(NSString*) launchImage
andInfo:(NSDictionary*) userInfo
{
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
txtExpiryDate.text, #"ExpiryDate",
txtRegNo.text , #"RegNo",
nil];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone systemTimeZone];
localNotification.userInfo = userInfo;
localNotification.alertBody = alertText;
localNotification.alertAction = alertAction;
NSLog(#"Repeat Type:%#",txtRepeat.text);
if([txtRepeat.text isEqualToString:#"Every Week"])
{
NSLog(#"Every Week");
localNotification.repeatInterval = 256;
}
else if([txtRepeat.text isEqualToString:#"Every Month"])
{
NSLog(#"Every Month");
localNotification.repeatInterval = NSMonthCalendarUnit;
}
else if([txtRepeat.text isEqualToString:#"Every Day"])
{
NSLog(#"Every Day");
localNotification.repeatInterval = NSDayCalendarUnit;
}
if(soundfileName == nil)
{
localNotification.soundName = UILocalNotificationDefaultSoundName;
}
else
{
localNotification.soundName = soundfileName;
}
NSLog(#"appDelegate.BadgeNumber:%d",appDelegate.BadgeNumber);
localNotification.alertLaunchImage = launchImage;
appDelegate.BadgeNumber = appDelegate.BadgeNumber + 1;
localNotification.applicationIconBadgeNumber = appDelegate.BadgeNumber;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
}
I have worked by comparing current date to expiry date. But this work only if the app is in foreground and i cannot cancelnotification not background for a particular date. Please find the below code for the same:-
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
BadgeNumber = 0;
application.applicationIconBadgeNumber = BadgeNumber;
NSArray *localNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDateFormatter *formatter =[[[NSDateFormatter alloc]init] autorelease];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSLog(#"localNotifications Count %d",localNotifications.count);
for (UILocalNotification *notify in localNotifications)
{
//notify.applicationIconBadgeNumber = 0;
NSString *ExpiryDateString = [notify.userInfo objectForKey:#"ExpiryDate"];
NSDate *ExpiryDate = [formatter dateFromString:ExpiryDateString];
NSDate * NextFireDate = nil;
NSLog(#"Expiry Date:%#",ExpiryDateString);
if(notify.repeatInterval == NSDayCalendarUnit)
{
NSLog(#"Repeat Every Day");
NextFireDate = [[NSDate date] dateByAddingDays:1];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
if(notify.repeatInterval == NSWeekCalendarUnit)
{
NSLog(#"Repeat Every Day");
NextFireDate = [[NSDate date] addTimeInterval:D_WEEK];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
if(notify.repeatInterval == NSMonthCalendarUnit)
{
NSLog(#"Repeat Every Day");
//NextFireDate = [[NSDate date] addTimeInterval:D_Month];
NextFireDate = [self CalculateExipiryDateForMonth];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
NSComparisonResult result = [NextFireDate compare:ExpiryDate];
NSLog(#"NSComparisonResult:%d",result);
if(result == NSOrderedDescending)
{
NSLog(#"Cancell......... Notification");
NSLog(#"notify :::%#",notify);
}
else
{
NSLog(#"Re-Schedule Notification");
BadgeNumber = BadgeNumber + 1;
notify.applicationIconBadgeNumber = BadgeNumber;
NSLog(#"BadgeNumber:%d",BadgeNumber);
[[UIApplication sharedApplication] scheduleLocalNotification:notify];
}
}
}
-(NSDate*) CalculateExipiryDateForMonth
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.month = 1;
NSDate *nextMonth = [gregorian dateByAddingComponents:components toDate:[NSDate date] options:0];
[components release];
NSDateComponents *nextMonthComponents = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:nextMonth];
NSDate *expiryDay = [gregorian dateFromComponents:nextMonthComponents];
NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
dayComponent.day = -1;
NSDate *NewExpiry = [gregorian dateByAddingComponents:dayComponent toDate:expiryDay options:0];
[gregorian release];
[dayComponent release];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSLog(#"Next Exipiry Date -----:%#",[formatter stringFromDate:NewExpiry]);
return NewExpiry;
}
In short, no, you cannot cancel a UILocalNotification while your app is running in the background.
**Apple RESPONSE:-**
I'm responding to your question about UILocalNotification.
At this time UILocalNotification does not have a way to specify an expiry
date or number of repetitions before the notification is automatically
canceled.
The closest you can get today is to schedule up to 64 individual
notifications instead of using the repeat interval.
But you're correct; if the user doesn't ever bring your app to the
foreground, it won't have the opportunity to cancel or reschedule local
notifications.
I highly recommend that you file an enhancement request at <
https://developer.apple.com/bugreporter> asking for this functionality in a
future release of iOS.
You also asked about what happens to local notifications when the user
removes your app from the device. iOS stores the local notifications so
that they are still scheduled if the user deletes and then reinstalls the
app.
When your app runs, it can check the scheduledLocalNotifications property
of UIApplication and remove any notifications that are no longer relevant.
Best regards,
--gc
Garth Cummings
Apple Developer Technical Support