In my app I have objects that trigger Local Notifications.
When the app is in the background the Local Notifications are fired when it's their time to be fired, and that works fine.
For some reason, the Badge Number is not updated.
When setting the Notification object, I use the following code:
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = obj.noteMeDate; //obj is an object for which the notification is created...
localNotification.alertBody = [NSString stringWithFormat:#"Note: %#", obj.title];
localNotification.alertAction = #"Show Me";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; //this is NOT WORKING...
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Anyone?
You can't increase the badge number, you can only set it to a certain number. At the time you're scheduling the notification, applicationIconBadgeNumber is 0 (since you're running the application in the foreground), thus every notification is showing only 1 in the badge.
Technically you cannot increment the badge icon directly but there is a way.
int num = [UIApplication sharedApplication].applicationIconBadgeNumber;
[UIApplication sharedApplication].applicationIconBadgeNumber = num + 1;
Related
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];
I need to clear already displayed local notification from Notification Centre programmatically. Following this link I implemented suggested solution, but the problem is that eventArray from this example always has 0 elements. When I swipe down to display Notification Centre I see 4 notifications that I've created previously. So in this case I expect this array to have 4 elements, but it has 0. Any idea why is this so? I've tried on iOS 8.3 and 9.2.1 and array is 0 on both of them.
iOS has 2 ways of presenting local notifications:
From Notification Center:
You can't swipe away notification from left to right.
You can swipe notification from right to left (deleting single notification from the list).
You can click on the notification, after which your app will start and notification will be removed from Notification Center (handled by iOS system)
From Lock screen:
Available only if you enable this setting from iPhone/iPad settings: http://www.imore.com/how-disable-notification-center-lock-screen-your-iphone-and-ipad
You can swipe notification from left to right (your app will be started, handled by iOS). In this case notification from Notification Center is not deleted (iOS doesn't delete it, and doesn't allow deleting a single notification from code after notification is already presented to the user in Notification Center).
You can swipe notification from right to left (deleting single notification from the list, handled by iOS. Notification Center notification is also deleted, handled by iOS).
You can't click on the notification.
EDIT:
Here is code sample how I did it:
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"1";
localNotification.alertTitle = #"1";
localNotification.userInfo = uniqueDictIdentifier1;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
UILocalNotification *localNotification2 = [[UILocalNotification alloc] init];
localNotification2.alertBody = #"2";
localNotification2.alertTitle = #"2";
localNotification2.userInfo = uniqueDictIdentifier2;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification2];
....
//2 more notifications are created like this
And then there is code for filtering all notifications:
NSArray *eventArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++) {
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
if ([userInfoCurrent isEqualToDictionary:uniqueDictIdentifier1]) {
[[UIApplication sharedApplication] cancelLocalNotification:oneEvent];
break;
}
}
For saving a notification for a unique id
NSDictionary * infoDict = #{ #"alarmUiqueId" : uID,
};
NSLog(#"%#",infoDict);
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
fromDate:fireDate];
fireDate = [fireDate dateByAddingTimeInterval:-comp.second];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = fireDate;
localNotif.timeZone = [NSTimeZone localTimeZone];
localNotif.alertBody = desString;
localNotif.userInfo = infoDict;
localNotif.repeatInterval = NSCalendarUnitDay;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif]
and for delete a paritcular notification write this code.
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for(UILocalNotification *notification in notificationArray)
{
NSLog(#"%#",[notification.userInfo valueForKey:#"alarmUiqueId"]);
if ([[notification.userInfo valueForKey:#"alarmUiqueId"] isEqualToNumber: health.uniqueId])
{
[[UIApplication sharedApplication] cancelLocalNotification:notification] ;
}
}
My understanding is below:
You can not get the information of already notified LocalNotification with scheduledNotifications.
My resolution is that just keep UILocalNotification instance in your singleton object in your application, and call cancelLocalNotification with the instance when you want to delete from Notification Center.
Is this could be your help ?
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.
}
}
-(void)notifyMe
{
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0.1];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"Alert";
localNotification.alertAction = #"Local notification";
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertLaunchImage = nil;
localNotification.userInfo = nil;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
This is the method I am calling for local notification. This is working fine with other applications. But with my working one, notification is coming but with no sound.
I guess there is some problem with app setting, but I am unable to find it out.
I found your question as I had run into the same problem. Turns out it was a simple fix on my part, my code was fine all I had to do was enable push notifications for my app (which I had already done but was getting no sound or badge), and then switch Badge App Icon and Sound to ON.
I'm surprised there have been no other answers to this question in 6 months.