I am trying to setup a UILocalNotification to run every 30 seconds using the following logic, however it seems to be misbehaving. There are 2 issues:
When the notifications get fired there seems to be a lot of them all at once, rather than 1 every 30 seconds.
The application icon badge number doesn't seem to increase. It just stays at 1.
Please can someone help me work out what I've done wrong?
// Create 'base' notification we can use
UILocalNotification *baseNotification = [[UILocalNotification alloc] init];
baseNotification.timeZone = [NSTimeZone defaultTimeZone];
baseNotification.repeatInterval = NSMinuteCalendarUnit;
baseNotification.alertBody = #"My Message.";
baseNotification.alertAction = #"My Alert Action";
baseNotification.soundName = UILocalNotificationDefaultSoundName;
UILocalNotification *alertOne = [baseNotification copy];
alertOne.applicationIconBadgeNumber++;
alertOne.fireDate = [[NSDate date] dateByAddingTimeInterval:30];
[[UIApplication sharedApplication] scheduleLocalNotification:alertOne];
UILocalNotification *alertTwo = [baseNotification copy];
alertTwo.applicationIconBadgeNumber++;
alertTwo.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
[[UIApplication sharedApplication] scheduleLocalNotification:alertTwo];
Try this one.
UILocalNotification *baseNotification = [[UILocalNotification alloc] init];
baseNotification.timeZone = [NSTimeZone defaultTimeZone];
baseNotification.repeatInterval = NSMinuteCalendarUnit;
baseNotification.alertBody = #"My Message.";
baseNotification.alertAction = #"My Alert Action";
baseNotification.soundName = UILocalNotificationDefaultSoundName;
UILocalNotification *alertOne = [baseNotification copy];
alertOne.fireDate = [[NSDate date] dateByAddingTimeInterval:30];
alertOne.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
UILocalNotification *alertTwo = [baseNotification copy];
alertTwo.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
alertTwo.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
There is currently no way possible to achieve custom repeats with intervals.
However, the notification system can queue up to 64 notifications so the closest thing you could do is to manually set as many notifications as you need (with each one having a different number for the badge and a different fireDate) and then have your notifications list updated by setting new ones when you're running low on them.
This will return how many notifications you've in queue:
[[[UIApplication sharedApplication] scheduledLocalNotifications] count]
There's also this post that I would recommend you reading for further help:
iOS badge number live update
Good luck!
Regarding second point, you're increasing the badge number of the copy not the original notification. And since the original has a zero badge number you'll always get a copy with zero badge number too and increasing it will make it always 1.
The solution is to increase the badge of the original notification right before making the copy:
...
baseNotification.applicationIconBadgeNumber++;
UILocalNotification *alertOne = [baseNotification copy];
alertOne.fireDate = [[NSDate date] dateByAddingTimeInterval:30];
[[UIApplication sharedApplication] scheduleLocalNotification:alertOne];
baseNotification.applicationIconBadgeNumber++;
UILocalNotification *alertTwo = [baseNotification copy];
alertTwo.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
[[UIApplication sharedApplication] scheduleLocalNotification:alertTwo];
According NSObject class reference :
copy - Returns the object returned by copyWithZone:
And copyWithZone returns a shallow copy.
So its like all notification have same properties .
Hence , badge number is always "1" and fireDate is same for all notifications. i.e. last one that you apply .
Hence , notifications get fired at same time.
Hope , it helps.
I think you get a lot of notifications every 30 seconds is because you did not cancel previous notifications. Add this line at the top of your code.
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Related
I have simple UILocalNotification:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"Message";
notification.alertAction = #"Action";
notification.soundName = UILocalNotificationDefaultSoundName;
notification.category = kCategoryIdentifier;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
Is it possible, to repeat notification once, for example after two minutes? I want behaviour exacly, like in Messages app.
I have tried to set repeatInterval property of notification object, but:
Notification will be presented to user every two minutes, not repeated only once
System shows to user new notification, not repeat the old one. User see two notifications, one with timestamp 2 minutes after another.
Which is not what I've expected.
Also, because of second reason, I don't want to schedule two separate notifications.
Edit: In my app time when something happend is very important. Because of that, in lock screen, when notification is repeated, I want user to know that is something that happend earlier, not in time when notification arrives. So repeated notification should have timestamp of first notification.
Yes, you can set repeatInterval.
See documentation here
The calendar interval at which to reschedule the notification.
Declaration SWIFT var repeatInterval: NSCalendarUnit OBJECTIVE-C
#property(nonatomic) NSCalendarUnit repeatInterval
try this code
localNotif.timeZone = [NSTimeZone systemTimeZone];
localNotif.alertBody = #"Message";
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber=1;
NSLog(#"LocalNotif.soundName %#",localNotif.soundName);
for (int i=0; i<20; i++)
{
localNotif.fireDate = [repeatAlarm dateByAddingTimeInterval:120*i];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
I want to schedule local notification in my game.
First notification will come two hours after game play has ended.
After that another one come in the next 24 hours if still no gameplay. If gameplay resets to after 2 hours, then every 24 hrs until they enter game.
I would be very thankful to you if you can help me.
Here is my code:
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.alertBody = [self.notifyArray objectAtIndex:index];
NSTimeInterval sec = 7200;
notif.fireDate = [NSDate dateWithTimeIntervalSinceNow:sec];
notif.repeatInterval = NSDayCalendarUnit;
notif.soundName = UILocalNotificationDefaultSoundName;
NSLog(#"notif : %u",notif.repeatInterval);
notif.applicationIconBadgeNumber += 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
//notif.fireDate = [NSDate dateWithTimeIntervalSinceNow:20];
//[[UIApplication sharedApplication] scheduleLocalNotification:notif];
Try to debug first by checking the scheduled notifications list. You can see this thread for details iOS find list of Local Notification the app has already set
First give an 'identifier' to your local notification. Then and when app goes to background, use that identifier to identify notification from scheduled notifications of your application. And reschedule it after 2 hours , with repeat interval of day.
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
if ( oneEvent.identifier = yourNotificationIdentifier){
//Reschedule oneEvent.
}
}
I've created a reminder in my app, I want the remainder to be notified before 5 minutes of its actual time. If yes, is there any default available for doing it?
Thanks!
For this you can add two reminders, one for actual time and other 5 minutes before the actual time. Now you can do different things on receiving both reminders..
you can remove 5 min by creating new date from your date by
NSDate *fiveMinutesBeforeDate = [NSDate dateWithTimeInterval:-60*5 sinceDate:dateFromFirstString];
and create local notification by following cate and set this date to firedate of local notification
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fiveMinutesBeforeDate;
localNotification.alertBody = [NSString stringWithFormat:#"Alert Fired at %#", fiveMinutesBeforeDate];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
I need to send a text message when the current time equals the time selected in the UIDatePicker. How might I do this? You don't need to include the code to send the message, I already have that coded. I've tried all sorts of things with NSTimer and if - then statements but none have worked.
Edit: Since I wrote this question I've found a better way to do things. I just need to set a local notification and when received execute my code with -(void)didRevieveLocalNotification. Here is what I have so that any googlers can hopefully be helped.
NSDate *pickerDate = [self.datePicker date];
//Set Local Notification
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.fireDate = pickerDate;
notif.timeZone = [NSTimeZone defaultTimeZone];
//----------------------------------------------------------------------
notif.alertBody = #"Tap to send your text message!";
notif.alertAction = #"send message...";
notif.soundName = #"sms_alert_nova.caf";
notif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
well i would use a local notification... something like this
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = theDate //The date that your picker has selected
notification.alertBody = #"Hey, the time just expired!"
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
Then in your AppDelegate
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
//Code to manage the notification logic
}
Hope this helps, the user will get the alert even if on background.. if on background the user must click the alert to let your application know that the local notification triggered, if he does (or he is on your app already, then the app delegate method will trigger letting your app know that the notification fired...
Hope this helps!
i am making reminder application there is table view and there is dates in cell and when that cell date become todays day UILocalNotification fires. for that i am using following code
-(void)notification {
// logic for local notification start
NSDateFormatter *Form = [[NSDateFormatter alloc] init];
[Form setDateFormat:#"dd/MM/yyyy"];
UILocalNotification *notification = [[UILocalNotification alloc] init];
for (int i=0;i<_convertedBdates.count;i++)
{
NSDate *date =[Form dateFromString:[_convertedBdates objectAtIndex:i ]];
// NSLog(#"date%#",date);
if(notification)
{
notification.fireDate = date;
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.alertBody = [NSString stringWithFormat:#"Today is %#\'s Birthday",[_combinedNameArray objectAtIndex:i]];
notification.alertAction = #"View";
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
// local notification logic ends here
}
now i have also implemented functionality of deleting cell from table view
now my problem is cell gets removed but its notification not there is no cell but when that date comes then notification fire.
how should i remove that particular notification when that cell is removed?
Edited: My initial answer was wrong, because I didn't realize that the OS copies UILocalNotifications when you schedule them, rather than just retaining them. So...
There are two ways to do this, as far as I can tell.
Cancel all notifications when a row is deleted, and then reschedule the remaining ones.
This is going to be more efficient if you don't have many notifications scheduled, and it will definitely be much easier to code. (Note: I don't know enough about the low-level things at work to say which is necessarily more efficient, but my guess is that the difference isn't really important.)
Whenever a row is deleted, simply call
[[UIApplcation sharedApplication] cancelAllLocalNotifications];
Then update _convertedBDates appropriately, and finally call your notification method again to reschedule new local notifications for those events that are still around.
Create unique identifiers for your local notifications
This is possibly the more efficient way, if you can come up with a good way to make those unique identifiers and if you have a lot of notifications scheduled. (Emphasis on possibly). One possibility is to use the time at which the notification will fire, if you can guarantee that no two notifications will fire at the same time. Other possibilities are the label for the notification (again if you can be sure of uniqueness). Whatever you decide to use for your unique identifier, you can store it by adding this outside your for loop:
self.uniqueIDArray = [[NSMutableArray alloc] init];
(where uniqueIDArray is an NSMutableArray* #property of your class) and then this right before you schedule the notification:
[uniqueIDArray addObject:whateverObjectYouUseForTheUniqueID];
notification.userInfo = [[NSDictionary alloc] initWithObjects:whateverObjectYouUseForTheUniqueID
forKeys:#"uniqueID"];
Then, in whatever method you're using to delete the cells, you would do something like this:
uniqueIDToDelete = [self.uniqueIDArray objectAtIndex:indexOfCellBeingDeleted];
NSArray *scheduledNotifications = [[UIApplication sharedApplication] scheduledNotifications];
UILocalNotification *notifToDelete;
for (UILocalNotification *notif in scheduledNotifications) {
if ([[notif.userInfo objectForKey:#"uniqueID"] isEqual:uniqueIDToDelete]) {
[[UIApplication sharedApplication] cancelLocalNotification:notif];
}
}
[self.uniqueIDArray removeObjectAtIndex:indexOfCellBeingDeleted];
I think you shouldn't use cell as source for notification. Use data model instead. Also you could remove notification easily
UPDATE
Model *model = [_array objectAtIndex:indexPath.row]; model.notificationID = // here you store created notification identifier
[[UIApplication sharedApplication] scheduledLocalNotifications] // contains all local notifications, you should search you need by ID and remove it using cancelLocalNotification method.
P.S. notification ID you can store in notification userInfo
Try this
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *notif = [notificationArray objectAtIndex:indexPath];
[[UIApplication sharedApplication] cancelLocalNotification:notif];