I have an app that uses UILocalNotification to set a repeating notification. When the user gives the app permission, I set a notification in the AppDelegate.m to repeat at 9pm every night but it's not firing consistently.
As far as I can tell, it seems like the notification will fire if the user opened the app at some point during the day (i.e. after the last notification fired at 9pm yesterday and before 9pm today when the next one fires), but when they don't open the app all day, no notification arrives.
I've tried cancelling all notifications in didFinishLaunchingWithOptions before creating a new one, and not cancelling and recreating them. I don't know what else to try or why the OS isn't handling this for me. I noticed when using other to do list apps on my phone that often the badge count doesn't update for the day until I open the app. Is this an iOS limitation? If so, why bother using repeatInterval if the OS can't handle it for you unless your app gets opened anyway?
Here's the method I use for creating my notification:
- (void)createLocalNotification {
// Create local notification
self.localnotif = [[UILocalNotification alloc] init];
self.localnotif.alertBody = #"Time to rate your day!";
self.localnotif.alertAction = #"Rate";
// Set a date of today for the date components
NSDate *date = [NSDate date];
NSDateComponents *dateComponents = [[NSCalendar autoupdatingCurrentCalendar]
components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay
| NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:date];
// Set the date components time to 9pm for notification
dateComponents.hour = 21;
dateComponents.minute = 0;
// Pass in userInfo dict
self.localnotif.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:#"mood rating", #"notification", nil];
NSDate *fireDate = [[NSCalendar autoupdatingCurrentCalendar] dateFromComponents:dateComponents];
// Set fireDate for notification and schedule it
self.localnotif.fireDate = fireDate;
self.localnotif.timeZone = [NSTimeZone systemTimeZone];
// Make the notification repeat every day
self.localnotif.repeatInterval = NSCalendarUnitDay;
[[UIApplication sharedApplication] scheduleLocalNotification:self.localnotif];
}
I call this method from didFinishLaunchingWithOptions in my AppDelegate.m like this:
if ([UIApplication sharedApplication].scheduledLocalNotifications.count >= 1) {
// handle notification here
} else {
[self createLocalNotification];
}
One thing that might be related in iOS 8, I think you need to register for notifications for local notifications. They will show up within the app if you haven't registered but will fail outside the app.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1
Related
I am working on Alarm module in my app. I have develop code which take date and time input from user and set Event on that particular time in my app.
Also i store information into my local database to display list of alarm set by user.
Now i want to delete entry from database when particular alarm executed (When UILocalNotification displayed into app i want to call database method to delete that entry from db)
I set Notification by this way
NSUserDefaults* preferences = [NSUserDefaults standardUserDefaults];
int notificationCount = [preferences integerForKey:#"notification_count"];
notificationCount++;
NSDate* final_date = [calendar dateFromComponents:final_Components];
UILocalNotification *localNotification = [[UILocalNotification alloc]init];
localNotification.fireDate = final_date;
localNotification.alertBody=titleTextField.text;localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.applicationIconBadgeNumber = 1;
NSDictionary* userInfoDic = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:notificationCount] forKey:#"notification_id"]; localNotification.userInfo = userInfoDic;
localNotification.repeatInterval = 0;
[[UIApplication sharedApplication]scheduleLocalNotification:localNotification];
[preferences setInteger:notificationCount forKey:#"notification_count"];
I used Delegate didReceiveLocalNotification
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSString *itemName = [notification.userInfo objectForKey:#"notification_id"];
NSLog(#"userInfo is %#",itemName);
databaseObject.deleteNotification(itemName)
}
My problem is "didReceiveLocalNotification" only call in 2 case
1) When user using app (app in foreground).
2) when notification displayed and user click on notification
But in 3rd case when app is in background mode and notification displayed and if user don't click on notification Or second case is open app directly clicking on app icon or user clear notification at that time didReceiveLocalNotification delegate is not get called..
Is there any way to detect Notification fire in all case or any other method by using i can detect that notification has been fire and then i will execute my delete method.
Any help is appreciated
Thank you
Yes, you are right, you won't know the information of the notification if your notification fires while your app is suspended/terminated and user didn't tap the notification to launch/active your app.
The only way to do this is to calculate the time every time your app is running and reschedule notifications and update your database.
For millisecond calculation:
NSInteger myMillisecond; //assume it exists
const NSTimeInterval oneSecondAsMilliseconds = 1000.0;
NSTimeInterval myTimeInterval = myMillisecond/oneSecondAsMilliseconds;
NSDate *currentDate = [NSDate date];
NSTimeInterval currentTimeStamp = [currentDate timeIntervalSince1970];
if (myTimeInterval > currentTimeStamp) {
//myTimeInterval is a later time than now
}
I'm not sure if an iOS app can post a notification from the background without internet connection? (so this is not a push notification, just to post from phone)
Example: An iOS app that plays music in background can prompt user how long the user has listened to music from background.
I think you should use local notification, please see the below code for local notification,
NSDate *alertTime = [[NSDate date]
dateByAddingTimeInterval:10];
UIApplication* app = [UIApplication sharedApplication];
UILocalNotification* notifyAlarm = [[UILocalNotification alloc]
init];
if (notifyAlarm)
{
notifyAlarm.fireDate = alertTime;
notifyAlarm.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm.repeatInterval = 0;
notifyAlarm.soundName = #"bell_tree.mp3";
notifyAlarm.alertBody = #"Staff meeting in 30 minutes";
[app scheduleLocalNotification:notifyAlarm];
}
With these requirements in the mind, the following code creates an NSDate object based on the current date and time plus 10 seconds. This date object is then used to schedule a notification with no repeats, a text message and the sound from the audio file
The local notifications in iOS can help you to fix the problem. May be this tutorial helps you.
I have made one sample application which fires local notification.
When notification fires it always shows banner in notification area in device, which I have shown in image.
But I want alert rather than this and want to perform action based upon selected option from that alert.
Code to fire local notification is given as below.
-(IBAction)setNotification:(id)sender{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
{
return;
}
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Get the year, month, day from the date
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSTimeZoneCalendarUnit|NSSecondCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:[NSDate date]];
// Set the second to be zero
components.minute = components.minute + 1;
components.second = 0;
// Create the date
NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:components];
NSLog(#"Fire Date :: %#",date);
localNotif.fireDate = date;
localNotif.alertBody = [NSString stringWithFormat:#"First Alarm"];
localNotif.alertAction =#"Ok";
localNotif.soundName=#"Alarm_1.mp3";
localNotif.applicationIconBadgeNumber = 1;
localNotif.alertAction = #"Application name";
localNotif.HasAction = true;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
Can any body please tell me if there is any mistake.
Thanks in advance.
Here is a quick and short answer. You cannot do that.
Apples documentation only states didReceiveLocalNotification. The way the notification is shown is not up to the developer. The user will choose how he wants to see notification using SETTINGS.
In your case, just wire up logic by implementing the delegate callback when the user taps on the notification.
Change the Type of Notification in Setting -> Notification Centre - > Your App -> Alert:
Originally from Quinn "The Eskimo!", as quoted by IBG:
"This depends on you mean. You have some control over how the
notification appears based on how you set the UILocalNotification
properties (things like alertBody, soundName, and so on). However, if
you're asking about the way in which those properties are interpreted
(the things the user can customise in Settings > Notifications), those
are user preferences and not exposed via any API."
You can get your notification in this method:
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
write this code for fetch the data from userInfo:
[[userInfo objectForKey:#"aps"] objectForKey:#"price"]];
use userInfo Dict to get The notification Value and after that you can use that data for Alert.
iam getting some date and time like appointment time. i want to remind the user before to that particular time.i googled and got some knowledge but still in small confusion where to write my code shall i in application entered back ground method and i have to use alert views or any other .please help me.
NSString *today=[NSString stringWithFormat:#"%# %#",appDelegate.appointmentDate,appDelegate.timeStart1];
NSLog(#"%#",today);
NSDateFormatter *format=[[NSDateFormatter alloc]init];
[format setDateFormat:#"MM/dd/yyyy hh:mm a"];
NSDate *date1=[format dateFromString:today];
NSLog(#"%#",date1);
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *datefo1 =[[NSDateComponents alloc]init];
[datefo1 setMinute:1];
[datefo1 setSecond:0];
NSDate *alerttime=[cal dateByAddingComponents:datefo1 toDate:date options:0];
UIApplication* app = [UIApplication sharedApplication];
UILocalNotification* notifyAlarm = [[UILocalNotification alloc]
init];
if (notifyAlarm)
{
notifyAlarm.fireDate = alerttime;
notifyAlarm.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm.repeatInterval = 0;
notifyAlarm.alertBody = #"you have an appointment in 30 minutes";
[app scheduleLocalNotification:notifyAlarm];
}
i want notification like on top i want to display some alert even my app is running and not running also. but its coming with out any message, where i am going wrong shall i need to use nsnotification center are some thing else. sorry for my poor english.thanks in advance
You're using local notifications, which is a good start, but you should know that local notifications are only displayed if your app is in the background. If your app is running in the foreground when the time comes you will need to display the notification yourself (UIView / UIAlertView).
You can schedule the local notification whenever you want, it really depends what editing you allow the user to do and, therefore, how much you might need to cancel the local notification and schedule a new version.
Few other things:
Consider using 'NSDate -dateByAddingTimeInterval' (it's just less code for your use case)
You're adding a minute to your date, so the alarm will be after the event (and say the appointment is in 30 minutes time ?)
Use NSLocalizedString for any string that will be displayed to the user
In the future, store less data in the appDelegate, that ins't what that class is for :)
I want to cancel an iOS local notification after a particular time.
For example : a week later
- (void)ViewDidLoad
{
NSDate *date = [NSdate date];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
//set some localNotif's properties
localNotif.repeatInterval = NSDayCalendarUnit;
localNotif.fireDate = date
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
How can I cancel localNotif after a week (7 days) and can you show me the code?
You can't do that unless your app is running in the foreground at the time the notification is due to be cancelled (in which case there would be no need to cancel it anyway).
The reason you can't do it is because you would need a timer to tell you when to cancel it, and you can't schedule a timer unless you are an app that has a background mode, in which case you could schedule a timer to notify you - but even background apps can be suspended still it would not be guaranteed.
See here
iOS Run Code Once a Day