I am trying to fire a method once a day at a given time. I've tried a few things but I can't really make it work. any advice would be appreciated. Also, it would be ideal if it would fire regardless of if the app is open or not. Is this possible?
UILocalNotification will let you fire a notification (but not a method) when your app is running in the background, or will call a delegate method you implement (application:didReceiveLocalNotification:) if the app is running in the foreground, or will call a method you must implement (application:didFinishLaunchingWithOptions:) when the user responds to the alert. Other than this, you will not be able to call a method when the app is not in the foreground, you will only be able to fire the the notification (which can display the badge, play a sound, etc).
By the way, consider filing a bug report with apple if this is a feature you want. I would like the ability to run methods in the background based on local notifications, without waiting for the user to respond first.
See Apple's example code:
- (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore {
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setDay:item.day];
[dateComps setMonth:item.month];
[dateComps setYear:item.year];
[dateComps setHour:item.hour];
[dateComps setMinute:item.minute];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
[dateComps release];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = [itemDate addTimeInterval:-(minutesBefore*60)];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(#"%# in %i minutes.", nil),
item.eventName, minutesBefore];
localNotif.alertAction = NSLocalizedString(#"View Details", nil);
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey];
localNotif.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
}
Related
For my App I don't want notifications to go off in the weekends.
So my idea was to cancel all the notifications at a specific time on Fridays, I would like to do this by scheduling the task, just like I schedule notifications (UILocalNotifications)
So for example I have this code for my alarms:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour:8];
[comps setMinute:25];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *fireDate = [gregorian dateFromComponents:comps];
UILocalNotification *alarm = [[UILocalNotification alloc] init];
alarm.fireDate = fireDate;
alarm.repeatInterval = NSDayCalendarUnit;
alarm.soundName = #"sound.aiff";
alarm.alertBody = #"Message..";
alarm.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:alarm];
Is there a way to cancel all the notifications with the same method, or does Apple not allow this?
You can cancel a local notification with:
[[UIApplication sharedApplication] cancelLocalNotification:notification];
You would need to loop through all the local notifications and cancel them if they are on the weekend. Loop through them with:
NSArray *notifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
[notifications enumerateObjectsUsingBlock:^(UILocalNotification *notification, NSUInteger idx, BOOL *stop){
if (/* notification.fireDate is on weekend */) {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
}
}];
However you will have to ensure the app runs on a Friday to perform the code to remove the weekend notifications.
But, why not just not schedule ones that are on the weekend in the first place?
You can cancel all the local notifications with the method
[[UIApplication sharedApplication] cancelAllLocalNotifications];
If you want to go through them, and maybe post the most important notifications, you could use scheduledLocalNotifications.
I am developing an app which allows you to set monthly reminders for bills,
I have looked through the datepicckers API and can't seem to find how to make it repeat each month.
How could I achieve this?
Custamize the code according to your need. For details refer UILocalNotification Class Reference
UILocalNotification *localNotification = [[[UILocalNotification alloc] init] autorelease];
localNotification.fireDate = date; //The date and time when the system should deliver the notification.
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = alertBody;
localNotification.alertAction = #"View";
localNotification.repeatCalendar = [NSCalendar currentCalendar];
localNotification.repeatInterval = NSMonthCalendarUnit;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
You need to use UILocalNotification APIs
Refer to
http://www.icodeblog.com/2010/07/29/iphone-programming-tutorial-local-notifications/
i used the local notification and schedule the fire date but when the app is in background and i open the notification tray to see the notification then the local notification is fire automatically but the fire date is remaining..is there any solution to solve that problem
This sounds like you have two issues. First, the local notification has been created with a fire date set in the past - that's why its appearing as soon as you open the app.
Secondly, you may be setting the notification's repeatInterval to a non-zero value, which will cause it to come up more than once.
See the below code for setting a local notification to fire at 3pm:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"This is a test alert";
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour: 15];
[comps setMinute: 0];
[comps setSecond: 0];
NSDate *threePM = [currentCalendar dateFromComponents:comps];
// Test if the current time is after three or not:
if(threePM != [threePM earlierDate: [NSDate date]])
{
comps = [[NSDateComponents alloc] init];
[comps setDay: 1];
threePM = [currentCalendar dateByAddingComponents: comps toDate: threePM options: 0];
}
localNotification.fireDate = threePM;
localNotification.repeatInterval = 0;
[[UIApplication sharedApplication] scheduleLocalNotification: localNotification];
I have a view controller which contains a field for user to enter date value.In contrast I have a field called "Remind Before Days" for the user to select when the notification should fire.If the remind before day is same day,then notification is set to fire on the date,but when the remind day is before 1 day,then notification should fire before one day the date set(specified).For this I have written a method called -(void)setNotification and here is the implementation code:
- (void)setNotification
{
//Set notification after confirmation of saved data
Class cls = NSClassFromString(#"UILocalNotification");
UILocalNotification *notif = [[cls alloc] init];
if (cls != nil)
{
textField = [self.fields objectAtIndex:3];
if (textField.text == #"Same Day")
{
notif.fireDate = [datePicker date];
notif.timeZone = [NSTimeZone defaultTimeZone];
}
else if(textField.text == #"1 Day")
{
NSDate *now = [datePicker date];
// set up date components
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:now];
[components setDay:-1];
// create a calendar to form date
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *newDate2 = [gregorian dateByAddingComponents:components toDate:now options:0];
notif.fireDate = newDate2;
notif.timeZone = [NSTimeZone defaultTimeZone];
}
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = textView.text;
notif.alertAction = #"View";
notif.soundName = #"lazy_afternoon.mp3";
notif.applicationIconBadgeNumber = 1;
textField = [self.fields objectAtIndex:1];
NSDictionary *userDict = [NSDictionary dictionaryWithObject:self.textField.text forKey:kReminder];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
}
}
Now as we are all aware that when the notification gets fired,the user clicks view.Then we show an alert,the implementation code is written in appDelegate.Here it is:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// For The Purpose Of Notification.
Class cls = NSClassFromString(#"UILocalNotification");
if (cls)
{
UILocalNotification *notification = [launchOptions objectForKey:
UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
NSString *reminderText = [notification.userInfo objectForKey:kReminder];
[self.viewController showReminder:reminderText];
}
}
application.applicationIconBadgeNumber = 0;
}
Now after local notification is received,we do the following i.e.:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
application.applicationIconBadgeNumber = 0;
NSString *reminderText = [notification.userInfo objectForKey:kReminder];
[self.viewController showReminder:reminderText];
}
Now I have set the -(void)setNotification action to right navigation right bar button item titled "Save" as follows:
-(IBAction)save:(id)sender
{
[self setNotification];
}
When I don't specify any condition for fire date i.e. simply assign as :
notif.fireDate = [datePicker date]; everything's fine with notification(no issues).
But when I do as the above i.e. condition for fire date,then the notification is not getting fired.Instead the alert is getting fired when I click save.Also when I quit the simulator,I could see some thread problem.I don't understand what's wrong with the code (implementation).I have gone through several links,also the apple documentation of UILocalNotification.Couldn't find out any property or method to set fire Date according to conditions.
I found out a method "repeatTimeInterval" which is relavant and applicable when a notification must be repeated weekly,yearly etc..which doesn't suit the requirement that the "date to be fired is this when the remind days in textField is this"
Can any one please guide me right,
Thanks all in advance :)
I believe if you check this link out you will find out. But from what I have seen the code you have provide is from this site anyway.
http://useyourloaf.com/blog/2010/7/31/adding-local-notifications-with-ios-4.html
I know I arrived a little late, but for me, the error on your code is here:
if (textField.text == #"Same Day")
Because you can't compare NSStrings using the operator ==. I think that if you use isEqualToString:(NSString*) it will work properly. It would be great if you could edit your original post and fix the code, so people looking for info about local notifications won't run into the same problem.
I am currently scheduling local notifications to appear once per day at 6PM if a user has not already opened the app that day. If the user has already loaded the application, then I want to cancel the notification for that day and schedule a new one for tomorrow at 6PM. The notification displays properly, however, when I try to iterate of the list of scheduled notifications (this is not the only local notification I have in the application), the [[UIApplication sharedApplication] scheduledLocalNotifications] array is always empty. Below is the code snippet that is giving me trouble:
// See if we need to create a local notification to tell the user that they can receive a daily reward
NSArray *notifications = [[UIApplication sharedApplication] scheduledLocalNotifications]; // <- This is always empty
// Iterate over all the pending notifications
for( int iter = 0; iter < [notifications count]; iter++ )
{
UILocalNotification* localNotification = [notifications objectAtIndex:iter];
if( [[localNotification.userInfo objectForKey:#"source"] isEqualToString:#"dailyReminder"] )
[[UIApplication sharedApplication] cancelLocalNotification:localNotification];
}
NSCalendar* calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *nowComponents = [calendar components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSSecondCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:serverDate];
int hour = [nowComponents hour];
int minute = [nowComponents minute];
int second = [nowComponents second];
int hoursToAdd = 18 - hour;
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setDay:1];
[comps setHour:hoursToAdd];
[comps setMinute:-minute];
[comps setSecond:-second];
NSDate *tomorrow6PM = [calendar dateByAddingComponents:comps
toDate:serverDate
options:0];
NSMutableDictionary* userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:#"dailyReminder" forKey:#"source"];
scheduleNotification(tomorrow6PM, NSLocalizedString(#"Come Back!", #"daily reminder notification message"), NSLocalizedString(#"Launch", #"daily reminder notification button text"), [UIApplication sharedApplication].applicationIconBadgeNumber+1, userInfo);
the scheduleNotification function is straightforward and just constructs a local notification:
void scheduleNotification(NSDate* fireIn, NSString* bodyText, NSString* alertText, NSUInteger badgeCount, NSMutableDictionary* userInfo)
{
static int appCount = 0;
appCount += 1;
if(!isLocalNotificationEnabled())
return;
Class localNotificationClass = NSClassFromString(#"UILocalNotification");
UILocalNotification* localNotification = [[localNotificationClass alloc] init];
if(!localNotification)
return;
localNotification.fireDate = fireIn;
localNotification.timeZone = [NSTimeZone systemTimeZone];
localNotification.alertBody = bodyText;
localNotification.alertAction = alertText;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = badgeCount;
localNotification.userInfo = userInfo;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
}
I don't understand why the array of local notifications is always empty. Like I said before the notifications display at the correct time, so they are getting scheduled. Any help is appreciated.
Having similar issues right now. My guess here is that iOS does not schedule the notifications immediately but only at the end of the current run loop. I am running into these problems when setting the scheduledLocalNotifications property several times in the same run loop and changes don't seem to be updated accordingly. I think I will just keep a copy of the local notifications array myself and only set scheduledLocalNotifications and never read it.
localNotification.fireDate = fireIn;
in this line check wheather "fireIn" is object of NSDate or NSString.
If it's NSString convert it into NSDate object with help of NSDateformatter and then assing it to localNotification fireDate.
I was facing same problem previously and resolved it with above mentioned steps.
if the schedule has invalid fire date, it will not get scheduled and result empty array returned, because there never has a valid one schedule, try to print out your localNotification like below, you may find out the problem.
NSLog(#"Notification--->: %#", localNotification);