I have added a local notification programmatically like below:
UILocalNotification *eventLocalNotification=[[UILocalNotification alloc]init];
eventLocalNotification.fireDate=myDate;
eventLocalNotification.timeZone=[NSTimeZone defaultTimeZone];
eventLocalNotification.alertBody=#"My notification";
eventLocalNotification.soundName=UILocalNotificationDefaultSoundName;
Can I change the firingDate, timeZone, alertBody, or any other property?
After searching a lot over internet, I got a thing that we can't edit a UILocal Notification once added. But sure there is another way that I have found.
Get all the Local notification of your device.
Search the respective local notification
Cancel that notification
Create a New one
Below is the method to add the notification.
-(void)setLocalNotification
{
UILocalNotification *eventLocalNotification = [[UILocalNotification alloc]init];
eventLocalNotification.fireDate = //set firing Date of NSDate type
eventLocalNotification.timeZone = [NSTimeZone defaultTimeZone];
eventLocalNotification.alertBody = [NSString stringWithFormat:#"An event has arrived\n Event Name: %#",notificationName.Text];
eventLocalNotification.soundName = UILocalNotificationDefaultSoundName;
if ([repeat isEqualToString:#"Once"]){
eventLocalNotification.repeatInterval = 0;
}else if ([repeat isEqualToString:#"Daily"]){
eventLocalNotification.repeatInterval = NSDayCalendarUnit;
}else if ([repeat isEqualToString:#"Weekly"]){
eventLocalNotification.repeatInterval = NSWeekCalendarUnit;
}else if ([repeat isEqualToString:#"Monthly"]){
eventLocalNotification.repeatInterval = NSMonthCalendarUnit;
}else if ([repeat isEqualToString:#"Yearly"]){
eventLocalNotification.repeatInterval = NSYearCalendarUnit;
}
NSDictionary *info = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"%#",notificationName.text] forKey:#"name"];
eventLocalNotification.userInfo = info;
NSLog(#"notification userInfo gets name : %#",[info objectForKey:#"name"]);
[[UIApplication sharedApplication] scheduleLocalNotification:eventLocalNotification];
NSLog(#"Notification created");
}
Below is the function to cancel the notification
-(void)cancelLocalNotification
{
UILocalNotification * notificationToCancel=nil;
for(UILocalNotification * aNotif in [[UIApplication sharedApplication] scheduledLocalNotifications])
{
NSLog(#"%#",[aNotif.userInfo objectForKey:#"name"]);
if([[aNotif.userInfo objectForKey:#"name"] isEqualToString:notificationName ])
{
notificationToCancel = aNotif;
[[UIApplication sharedApplication] cancelLocalNotification:notificationToCancel];
NSLog(#"Notification Cancelled");
break;
}
}
}
Hope you will get benefit from it. Best of Luck
To set your date and time, you will have to use NSDateComponents and instantiate NSDate twice. One for current date and another will be your desirable date. Than set desirable NSDate's instance to fireDate of UILocalNotification's object.
eventLocalNotification.fireDate = desiredDate;
for timezone, keep it to default the way you did.
eventLocalNotification.timeZone = [NSTimeZone defaultTimeZone];
Alert body could be anything, just put your context.
eventLocalNotification.alertBody = #"DESIRED CONTEXT";
I'm trying to play audio file at particular time which i have set.for that I have added audio in "UIBackgroundModes" in info.plist and backgroundtaskidentifier in didEnterBackground.Its working in simulator but not in device.Can anyone help to solve this.
Thanks in Advance...
You can check out this reference app with streaming and backgrounding of audio.
EDIT:
Example of a local notification w/ attached sound. More detail here.
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"Application entered background state.");
// bgTask is instance variable
NSAssert(self->bgTask == UIInvalidBackgroundTask, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIInvalidBackgroundTask;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
while ([application backgroundTimeRemaining] > 1.0) {
NSString *friend = [self checkForIncomingChat];
if (friend) {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif) {
localNotif.alertBody = [NSString stringWithFormat:
NSLocalizedString(#"%# has a message for you.", nil), friend];
localNotif.alertAction = NSLocalizedString(#"Read Message", nil);
localNotif.soundName = #"alarmsound.caf";
localNotif.applicationIconBadgeNumber = 1;
[application presentLocalNotificationNow:localNotif];
[localNotif release];
friend = nil;
break;
}
}
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIInvalidBackgroundTask;
});
}
If I understand you correctly, you want to play a sound at a particular time, no matter if your app is active and foregrounded at that time? Your only (app review-friendly) option is to schedule a local notification, as in slf's answer. UIBackgroundModes won't help you: the audio background mode is for being allowed to execute code while backgrounded only when you start playing audio when you are foregrounded. Example usages are music players and radio apps.
If you explain your use case more thoroughly, I might have a better answer.
I have a method that activates a local notification.
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = itemDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = [mainTitle text];
// Set the action button
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
The problem is that if you call several times the method, do not overwrite the localNotif, but it adds another. How do I delete the old every time?
Thanks!
Save the local notification object (say in an ivar), and do:
[[UIApplication sharedApplication] cancelLocalNotification:previousNotification];
You can also clear all local notifications with cancelAllLocalNotifications.
Make localNotif a property or instance variable of the class that contains this method.
I am developing an iPhone alarm app based on local notifications.
On deleting an alarm, the related local notification should get cancelled. But how can I determine exactly which object from the array of local notifications is to be cancelled?
I am aware of [[UIApplication sharedApplication] cancelLocalNotification:notification] method but how can I get this 'notification' to cancel it?
You can save a unique value for key in your local notification's userinfo.
Get all local notification, loop through the array and delete the particular notification.
Code as follows,
OBJ-C:
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
NSString *uid=[NSString stringWithFormat:#"%#",[userInfoCurrent valueForKey:#"uid"]];
if ([uid isEqualToString:uidtodelete])
{
//Cancelling local notification
[app cancelLocalNotification:oneEvent];
break;
}
}
SWIFT:
var app:UIApplication = UIApplication.sharedApplication()
for oneEvent in app.scheduledLocalNotifications {
var notification = oneEvent as UILocalNotification
let userInfoCurrent = notification.userInfo! as [String:AnyObject]
let uid = userInfoCurrent["uid"]! as String
if uid == uidtodelete {
//Cancelling local notification
app.cancelLocalNotification(notification)
break;
}
}
UserNotification:
If you use UserNotification (iOS 10+), just follow this steps:
When creating the UserNotification content, add an unique identifier
Remove specific pending notification using removePendingNotificationRequests(withIdentifiers:)
Remove specific delivered notification using removeDeliveredNotifications(withIdentifiers:)
For more info, UNUserNotificationCenter
Other Option:
First of All, when you create local notification, you can store it in user defaults for future use, Local notification object can not be stored directly in user defaults, This object needs to be converted into NSData object first, and then NSData can be stored into User defaults. Below is code for that:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:localNotif];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:#"%d",indexPath.row]];
After you have stored and scheduled local notification, In future, requirement may arise that you need to cancel any of notification that you created earlier, So you can retrieve it from User defaults.
NSData *data= [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"%d",UniqueKey]];
UILocalNotification *localNotif = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(#"Remove localnotification are %#", localNotif);
[[UIApplication sharedApplication] cancelLocalNotification:localNotif];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"%d",UniqueKey]];
Hope This helps
Here is what i do.
When creating your notification do this:
// Create the notification
UILocalNotification *notification = [[UILocalNotification alloc] init] ;
notification.fireDate = alertDate;
notification.timeZone = [NSTimeZone localTimeZone] ;
notification.alertAction = NSLocalizedString(#"Start", #"Start");
notification.alertBody = **notificationTitle**;
notification.repeatInterval= NSMinuteCalendarUnit;
notification.soundName=UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification] ;
when trying to delete it do this:
NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ;
for (UILocalNotification *localNotification in arrayOfLocalNotifications) {
if ([localNotification.alertBody isEqualToString:savedTitle]) {
NSLog(#"the notification this is canceld is %#", localNotification.alertBody);
[[UIApplication sharedApplication] cancelLocalNotification:localNotification] ; // delete the notification from the system
}
}
This solution should work for multiple notifications, and your not managing any arrays or dictionaries or user defaults. Your simply using the data you've already saved to the systems notification database.
Hope this helps future designers and developers.
Happy coding guys! :D
Scheduling and removeNotification in swift:
static func scheduleNotification(notificationTitle:String, objectId:String) {
var localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 24*60*60)
localNotification.alertBody = notificationTitle
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.applicationIconBadgeNumber = 1
//play a sound
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertAction = "View"
var infoDict : Dictionary<String,String!> = ["objectId" : objectId]
localNotification.userInfo = infoDict;
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
static func removeNotification(objectId:String) {
var app:UIApplication = UIApplication.sharedApplication()
for event in app.scheduledLocalNotifications {
var notification = event as! UILocalNotification
var userInfo:Dictionary<String,String!> = notification.userInfo as! Dictionary<String,String!>
var infoDict : Dictionary = notification.userInfo as! Dictionary<String,String!>
var notifcationObjectId : String = infoDict["objectId"]!
if notifcationObjectId == objectId {
app.cancelLocalNotification(notification)
}
}
}
Swift 4 solution:
UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in
for request in requests {
if request.identifier == "identifier" {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["identifier"])
}
}
}
iMOBDEV's solution works perfectly to remove a specific notification (e.g. after deleting the alarm) but it's specially useful when you need to selectively remove any notification that has already fired and is still on the notification center.
A possible scenario would be: the notification for an alarm fires, but the user opens the app without tapping on that notification and schedules that alarm again.
If you want to make sure only one notification can be on the notification center for a given item/alarm, it's a good approach. It also allows you not having to clear all notifications every time the app is opened, shall that fit the app better.
Upon creating a local notification, use NSKeyedArchiver to store it as Data in UserDefaults. You can create a key equal to what you're saving in the notification's userInfo dictionary. If it's associated with a Core Data object, you could use its unique objectID property.
Retrieve it with NSKeyedUnarchiver. Now you're able to delete it using the cancelLocalNotification method.
Update the key on UserDefaults accordingly.
Here's a Swift 3.1 version of that solution (for targets below iOS 10):
Store
// localNotification is the UILocalNotification you've just set up
UIApplication.shared.scheduleLocalNotification(localNotification)
let notificationData = NSKeyedArchiver.archivedData(withRootObject: localNotification)
UserDefaults.standard.set(notificationData, forKey: "someKeyChosenByYou")
Retrieve and delete
let userDefaults = UserDefaults.standard
if let existingNotificationData = userDefaults.object(forKey: "someKeyChosenByYou") as? Data,
let existingNotification = NSKeyedUnarchiver.unarchiveObject(with: existingNotificationData) as? UILocalNotification {
// Cancel notification if scheduled, delete it from notification center if already delivered
UIApplication.shared.cancelLocalNotification(existingNotification)
// Clean up
userDefaults.removeObject(forKey: "someKeyChosenByYou")
}
Swift Version, if need:
func cancelLocalNotification(UNIQUE_ID: String){
var notifyCancel = UILocalNotification()
var notifyArray = UIApplication.sharedApplication().scheduledLocalNotifications
for notifyCancel in notifyArray as! [UILocalNotification]{
let info: [String: String] = notifyCancel.userInfo as! [String: String]
if info[uniqueId] == uniqueId{
UIApplication.sharedApplication().cancelLocalNotification(notifyCancel)
}else{
println("No Local Notification Found!")
}
}
}
You can keep a string with the category identifier when scheduling the notification like so
localNotification.category = NotificationHelper.categoryIdentifier
and search for it and cancel when needed like so
let app = UIApplication.sharedApplication()
for notification in app.scheduledLocalNotifications! {
if let cat = notification.category{
if cat==NotificationHelper.categoryIdentifier {
app.cancelLocalNotification(notification)
break
}
}
}
swift 3-style:
final private func cancelLocalNotificationsIfIOS9(){
//UIApplication.shared.cancelAllLocalNotifications()
let app = UIApplication.shared
guard let notifs = app.scheduledLocalNotifications else{
return
}
for oneEvent in notifs {
let notification = oneEvent as UILocalNotification
if let userInfoCurrent = notification.userInfo as? [String:AnyObject], let uid = userInfoCurrent["uid"] as? String{
if uid == uidtodelete {
//Cancelling local notification
app.cancelLocalNotification(notification)
break;
}
}
}
}
for iOS 10 use:
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: [uidtodelete])
The UILocalNotification object you pass to cancelLocalNotification: will match any existing UILocalNotification object with matching properties.
So:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"foo";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
will present a local notification that can later be cancelled with:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"foo";
[[UIApplication sharedApplication] cancelLocalNotification:notification];
I use this function in Swift 2.0:
static func DeleteNotificationByUUID(uidToDelete: String) -> Bool {
let app:UIApplication = UIApplication.sharedApplication()
// loop on all the current schedualed notifications
for schedualedNotif in app.scheduledLocalNotifications! {
let notification = schedualedNotif as UILocalNotification
let urrentUi = notification.userInfo! as! [String:AnyObject]
let currentUid = urrentUi["uid"]! as! String
if currentUid == uidToDelete {
app.cancelLocalNotification(notification)
return true
}
}
return false
}
Inspired from #KingofBliss's Answer
For Repeated Reminders ( For example you want your alarm to fire on Sun, Sat and Wed at 4 PM , Then you have to make 3 alarms and set repeatInterval to NSWeekCalendarUnit ).
For making Once Only Reminder :
UILocalNotification *aNotification = [[UILocalNotification alloc] init];
aNotification.timeZone = [NSTimeZone defaultTimeZone];
aNotification.alertBody = _reminderTitle.text;
aNotification.alertAction = #"Show me!";
aNotification.soundName = UILocalNotificationDefaultSoundName;
aNotification.applicationIconBadgeNumber += 1;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit| NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: _reminderDate];
[componentsForFireDate setHour: [componentsForFireDate hour]] ; //for fixing 8PM hour
[componentsForFireDate setMinute:[componentsForFireDate minute]];
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
aNotification.fireDate = fireDateOfNotification;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey];
aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
For Making Repeated Reminder :
for (int i = 0 ; i <reminderDaysArr.count; i++)
{
UILocalNotification *aNotification = [[UILocalNotification alloc] init];
aNotification.timeZone = [NSTimeZone defaultTimeZone];
aNotification.alertBody = _reminderTitle.text;
aNotification.alertAction = #"Show me!";
aNotification.soundName = UILocalNotificationDefaultSoundName;
aNotification.applicationIconBadgeNumber += 1;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit| NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: _reminderDate];
[componentsForFireDate setWeekday: [[reminderDaysArr objectAtIndex:i]integerValue]];
[componentsForFireDate setHour: [componentsForFireDate hour]] ; // Setup Your Own Time.
[componentsForFireDate setMinute:[componentsForFireDate minute]];
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
aNotification.fireDate = fireDateOfNotification;
aNotification.repeatInterval = NSWeekCalendarUnit;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey];
aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
}
}
For Filtering you array to display it.
-(void)filterNotficationsArray:(NSMutableArray*) notificationArray{
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication] scheduledLocalNotifications]];
NSMutableArray *uniqueArray = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
for (int i = 0 ; i<_dataArray.count; i++) {
UILocalNotification *localNotification = [_dataArray objectAtIndex:i];
NSString * infoDict = [localNotification.userInfo objectForKey:#"kRemindMeNotificationDataKey"];
if (![names containsObject:infoDict]) {
[uniqueArray addObject:localNotification];
[names addObject:infoDict];
}
}
_dataArray = uniqueArray;
}
To remove Reminder even it was Once Only or Repeated :
- (void) removereminder:(UILocalNotification*)notification
{
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]];
NSString * idToDelete = [notification.userInfo objectForKey:#"kRemindMeNotificationDataKey"];
for (int i = 0 ; i<_dataArray.count; i++)
{
UILocalNotification *currentLocalNotification = [_dataArray objectAtIndex:i];
NSString * notificationId = [currentLocalNotification.userInfo objectForKey:#"kRemindMeNotificationDataKey"];
if ([notificationId isEqualToString:idToDelete])
[[UIApplication sharedApplication]cancelLocalNotification:currentLocalNotification];
}
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]];
[self filterNotficationsArray:_dataArray];
[_remindersTV reloadData];
}
I expanded on KingofBliss's answer a little, written this a little more Swift2-like, removed some unnecessary code, and added in some crash guards.
To start, when creating the notification, you need to make sure you set the uid (or any custom property really) of the notification's userInfo:
notification.userInfo = ["uid": uniqueid]
Then, when deleting it, you can do:
guard
let app: UIApplication = UIApplication.sharedApplication(),
let notifications = app.scheduledLocalNotifications else { return }
for notification in notifications {
if
let userInfo = notification.userInfo,
let uid: String = userInfo["uid"] as? String where uid == uidtodelete {
app.cancelLocalNotification(notification)
print("Deleted local notification for '\(uidtodelete)'")
}
}
Delete already delivered notification Swift5
UNUserNotificationCenter.current().getDeliveredNotifications{ (requests) in
for request in requests {
if request.request.identifier == "identifier"{
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["identifier"])
}
}
}
Is there a bug with the simulator and Local Notifications or am I doing something incorrectly.
// on button click fire off notification for 30 seconds from now
-(IBAction)scheduleNotification{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSDate *item = [NSDate dateWithTimeIntervalSinceNow:30];
if (localNotif == nil)
return;
localNotif.fireDate = item;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = NSLocalizedString(#"Test Notification", nil);
localNotif.alertAction = NSLocalizedString(#"View Details", nil);
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
}
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
// Handle the notificaton when the app is running
NSLog(#"Recieved Notification %#",notif);
}
didReceiveLocalNotification logs 2 notifications, but the simulator never actually displays a notification.
Recieved Notification <UIConcreteLocalNotification: 0x5943450>{fire date = 2010-08-25 09:36:25 -0400, time zone = America/New_York (EDT) offset -14400 (Daylight), repeat interval = 0, next fire date = 2010-08-25 09:36:25 -0400}
Recieved Notification <UIConcreteLocalNotification: 0x5c53e00>{fire date = 2010-08-25 09:36:25 -0400, time zone = America/New_York (EDT) offset -14400 (Daylight), repeat interval = 0, next fire date = (null)}
You won't see any alert if you receive local/push notification while your app is running. Unless you show your own alert in application: didReceiveLocalNotification:, certainly.