In my app delegate the method - (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification is never called.
This is how I create the notification:
UILocalNotification *notification = [[UILocalNotification alloc] init];
// set UUID, which we will store in userDefaults for later
NSMutableDictionary *myUserInfo = [[NSMutableDictionary alloc] init];
NSString *uuid = [[NSProcessInfo processInfo] globallyUniqueString];
[myUserInfo setValue:uuid forKey:KEY_UUID];
[myUserInfo setValue:#"month" forKey:KEY_UNIT];
[myUserInfo setObject:#YES forKey:KEY_RESCHEDULE];
NSInteger row = [_wurmProphylaxePickerView selectedRowInComponent:0];
switch (row) {
case 0:
[myUserInfo setValue:#2 forKey:KEY_FREQUENCY];
break;
case 1:
[myUserInfo setValue:#4 forKey:KEY_FREQUENCY];
break;
case 2:
[myUserInfo setValue:#6 forKey:KEY_FREQUENCY];
break;
default:
[myUserInfo setValue:#4 forKey:KEY_FREQUENCY];
break;
}
notification.userInfo = myUserInfo;
// calculate date for next notification, depends on the user's selection
NSDate *today = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *myComps = [[NSDateComponents alloc] init];
[myComps setMinute:1];
notification.fireDate = [calendar dateByAddingComponents:myComps toDate:today options:0];
notification.timeZone = [NSTimeZone localTimeZone];
notification.alertBody = #"My alertBody";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
And this is in my app delegates, but is never called:
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
BOOL repeat = [[userInfo objectForKey:KEY_RESCHEDULE] boolValue];
if (repeat)
{
NSInteger frequency = (NSInteger)[userInfo objectForKey:KEY_FREQUENCY];
NSString *unit = (NSString *)[userInfo objectForKey:KEY_UNIT];
NSString *uuid = (NSString *)[userInfo objectForKey:KEY_UUID];
// calculate date for next notification
NSDate *today = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *myComps = [[NSDateComponents alloc] init];
if ([unit isEqualToString:#"month"]) {
//[myComps setMonth:frequency];
[myComps setMinute:frequency];
} else {
}
// create new notification
UILocalNotification *newNotification = [[UILocalNotification alloc] init];
newNotification.fireDate = [calendar dateByAddingComponents:myComps toDate:today options:0];
newNotification.timeZone = [NSTimeZone localTimeZone];
newNotification.alertAction = notification.alertAction;
newNotification.alertBody = notification.alertBody;
newNotification.userInfo = notification.userInfo;
// schedule it
[[UIApplication sharedApplication] scheduleLocalNotification:newNotification];
}
}
tested on iOS 8, not sure about iOS 7...
If the app is not active when the notification fires, you would handle this in didFinishLaunchingWithOptions as illustrated by this example from the Handling Local and Remote Notifications section of the Local and Push Notifications Programming Guide:
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
[viewController displayItem:itemName]; // custom method
app.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
}
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
The didReceiveLocalNotification is called if the app was active when the notification fired.
Related
I am using local notifications in my app. It's firing ok, but when I open the app from the notification, I can't access notification's userinfo. This is how I am scheduling the notification:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.userInfo = #{#"eventId" : eventID};
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale preferredLanguages] objectAtIndex:0]];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss.S"];
NSDate *dateStart = [dateFormatter dateFromString: [eventDictionary valueForKey:#"time_start"]];
NSDate *newDate = [[NSDate date] dateByAddingTimeInterval:15];
notification.fireDate = newDate;
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.alertAction = #"Open";
notification.alertBody = #"Some title";
notification.soundName = UILocalNotificationDefaultSoundName;
//cfilipi: todo: verify if event date is bigger than today
if ([newDate timeIntervalSinceNow] > 0) {
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
This is how I am handling when I open the app from the notification (AppDelegate.m):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey] != nil){
//even when I cast to NSDictionary, it gets other class type (UIConcreteLocalNotification, I can't find any information about this class)
NSDictionary * aPush = (NSDictionary *)[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
[self handleLocalNotification:aPush];
}
}
-(void)handleLocalNotification:(NSDictionary *)localNotification{
NSDictionary *userInfo = [localNotification objectForKey:#"userinfo"];
NSString *eventId = [userInfo objectForKey:#"eventId"];
if ([eventId length] >= 1) {
//I use this key in some parts of my code
[[NSUserDefaults standardUserDefaults] setObject:eventId forKey:#"eventId"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
And this is what I get from LLDB when I am debugging didFinishLaunchingWithOptions:
(lldb) po aPush
<UIConcreteLocalNotification: 0x145b2ba0>{fire date = quinta-feira, 18 de dezembro de 2014 08:47:13 Horário de Verão de Brasília, time zone = America/Sao_Paulo (BRST) offset -7200 (Daylight), repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = (null), user info = {
eventId = 21;
}}
My question is: what am I doing wrong? Is there any way to convert this UIConcreteLocalNotification to NSDictionary? I have tried to convert it to UILocalNotification too, but I had no success.
Regards!
Do like this and it will work fine:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if ( notification != nil )
{
[self handleLocalNotification:[notification userInfo]];
}
}
You have not implemented
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
Implement this method and try.
This question already has an answer here:
IOS Cancelling Local Notifications
(1 answer)
Closed 8 years ago.
I am using Local Notifications. I want to delete already scheduled notifications.I don't know where to write the code.Here is my code ..
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
// Get the current date
NSDate *pickerDate = self.selectedDate;
NSLog(#" self.selectedDate %#", self.selectedDate);
// Break the date up into components
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit )
fromDate:pickerDate];
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit )
fromDate:pickerDate];
// Set up the fire time
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setDay:[dateComponents day]];
[dateComps setMonth:[dateComponents month]];
[dateComps setYear:[dateComponents year]];
[dateComps setHour:[timeComponents hour]];
// Notification will fire in one minute
[dateComps setMinute:[timeComponents minute]];
[dateComps setSecond:[timeComponents second]];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
NSLog(#"itemDate %#",itemDate);
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = itemDate;
NSLog(#"itemDate %#", localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = [_titleTextFieldObj text];
// Set the action button
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber =[[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
NSLog(#" localNotif.applicationIconBadgeNumber ++ %ld", (long)localNotif.applicationIconBadgeNumber );
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:[_titleTextFieldObj text] forKey:#"someKey"];
localNotif.userInfo = infoDict;
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
//UILocalNotification *notif = [notificationArray objectAtIndex:indexPath.row];
NSLog(#"notif %#",notificationArray);
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
Here I'm writing the removing of notification....
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
application.applicationIconBadgeNumber=1;
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;
NSLog(#"userInfoCurrent %#",userInfoCurrent);
NSString *uid=[NSString stringWithFormat:#"%#",[userInfoCurrent valueForKey:#"uid"]];
NSLog(#"uid %#",uid);
if ([uid isEqualToString:[notification.userInfo objectForKey:#"someKey"]])
{
//Cancelling local notification
[app cancelLocalNotification:oneEvent];
break;
}
}
if (notification) {
NSLog(#"notify %#",notification);
NSString *custom=[notification.userInfo objectForKey:#"someKey"];
NSLog(#"custom %#",custom);
NSString *newString = [custom stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"newString %#",newString);
NSLog(#"custmky%#",notification.description);
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Message" message:newString delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
alert.delegate=self;
[alert show];
}
}
I am new to UILocalNotifications and Objective-c. Can anyone please help me ....
You can cancel a UILocationNotification either by comparing fire dates to already scheduled UILocalNotifications or using its body.
An example of canceling by fire date:
UIApplication *application = [UIApplication sharedApplication];
NSDate *dateToCancel = nil; // Set this to the date you want to cancel
for (UILocalNotification *notification in [application scheduledLocalNotifications])
{
if (notification.fireDate == dateToCancel)
{
[application cancelLocalNotification:notification];
}
}
Now if you have a notification pointer you can just call the cancel local notification without needing to loop through already scheduled notifications. If you want you can also add an Id tag to the notification through key-object methods.
No matter in which class that code will lay, it's anywhere using UIApplication singleton...
You can cancel all notification using:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
If you want to remove a particular notification, you can use userinfo of notification object, when you create a local notification add a unique ID to that. Later you can use that ID for removing local notification.
For that you can use the following code:
NSString *notificationId = #"id_to_cancel";
UILocalNotification *notification = nil;
for(UILocalNotification *notify in [[UIApplication sharedApplication] scheduledLocalNotifications])
{
if([notify.userInfo objectForKey:#"ID"] isEqualToString:notificationId ])
{
notification = notify;
break;
}
}
[[UIApplication sharedApplication] cancelLocalNotification:notification];
This question already has answers here:
Removing UILocalNotification from notification tray programmatically
(7 answers)
Closed 8 years ago.
I am using UILocalNotifications in my app.Now my requirement is the local notification should be cancelled after it’s scheduled.
Here my Code…
-(void)LocalNotificationMethod{
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
// Get the current date
NSDate *pickerDate = self.selectedDate;
NSLog(#" self.selectedDate %#", self.selectedDate);
// Break the date up into components
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit )
fromDate:pickerDate];
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit )
fromDate:pickerDate];
// Set up the fire time
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setDay:[dateComponents day]];
[dateComps setMonth:[dateComponents month]];
[dateComps setYear:[dateComponents year]];
[dateComps setHour:[timeComponents hour]];
// Notification will fire in one minute
[dateComps setMinute:[timeComponents minute]];
[dateComps setSecond:[timeComponents second]];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
NSLog(#"itemDate %#",itemDate);
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = itemDate;
NSLog(#"itemDate %#", localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = [_titleTextFieldObj text];
// Set the action button
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber =[[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
NSLog(#" localNotif.applicationIconBadgeNumber ++ %ld", (long)localNotif.applicationIconBadgeNumber );
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:[_titleTextFieldObj text] forKey:#"someKey"];
localNotif.userInfo = infoDict;
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
//UILocalNotification *notif = [notificationArray objectAtIndex:indexPath.row];
NSLog(#"notif %#",notificationArray);
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
**In Appdelegate.m i wrote the code like…**
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
application.applicationIconBadgeNumber=1;
if (notification) {
NSLog(#"notify %#",notification);
NSString *custom=[notification.userInfo objectForKey:#"someKey"];
NSLog(#"custom %#",custom);
NSString *newString = [custom stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"newString %#",newString);
NSLog(#"custmky%#",notification.description);
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Message" message:newString delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
alert.delegate=self;
[alert show];
}
//UIApplication *application = [UIApplication sharedApplication];
NSString *notificationId = #"id_to_cancel";
//UILocalNotification *notification = nil;
for(UILocalNotification *notify in [[UIApplication sharedApplication] scheduledLocalNotifications])
{
if([[notify.userInfo objectForKey:#"someKey"] isEqualToString:notificationId ])
{
notification = notify;
break;
}
}
[[UIApplication sharedApplication] cancelLocalNotification:notification];
}
but it is not going into the loop …
I am new to this concept.Can anyone please help me to resolve this….
Thanks in advance.
You want to cancel a scheduled notification based on receiving another notification, if it is the case you need to put the loop before showing the Alert else your loop will never be executed. or in case you need to cancel/or not notification based button that will be taped in your AlertView you can put that code in your alertView delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
for(UILocalNotification *notify in [[UIApplication sharedApplication] scheduledLocalNotifications]){
if([[notify.userInfo objectForKey:#"someKey"] isEqualToString:#"someValue"]) {
[[UIApplication sharedApplication] cancelLocalNotification:notify];
break;
}
}
}
By Default all UILocalNotification is OneTime so it cancel automatically after its fireDate
And looks like you are trying to get same UILocalNotification.
Please try putting same code at different place you will get all your Scheduled Notifications Or try to get all Scheduled Notifications before fireDate.
In my case, I wish the notification to appear only once per day.
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
/*
* BeaconManager setup.
*/
self.beaconManager = [[ESTBeaconManager alloc] init];
self.beaconManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"xxxalotofnumbersxxx"];
self.beaconRegion = [[ESTBeaconRegion alloc] initWithProximityUUID: uuid
major: 41270
minor: 64913
identifier: #"RegionIdentifier"];
[self.beaconManager startMonitoringForRegion:self.beaconRegion];
}
- (void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{
UILocalNotification *notification = [UILocalNotification new];
notification.alertBody = #"Test";
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
I can try to manage it well by inserting immediately after the start?
if(notification.applicationIconBadgeNumber = 1;)
[self.beaconManager stopMonitoringForRegion:self.beaconRegion];
is there any other better solution to handle it? Thank you
Check how many local notification have been scheduled with [[UIApplication sharedApplication] scheduledLocalNotifications]; which returns a array of UILocalNotifcations. Then loop through all the UILocalNotification and check to see when it will be shown with its fireDate or userInfo.
Use repeatInterval property in UILocalNotifcation to keep track of your daily notifications raither then always creating a new notification.
if (![self isScheduledToday:[UIApplication sharedApplication].scheduledLocalNotifications]) {
// add new notifcation as its not scheduled and set repeatMode to NSDayCalendarUnit;
}
/**
* returns if there a schedule for today
*/
- (BOOL)isScheduledToday:(NSArray *)notifications {
for (UILocalNotification *notification in notifications) {
if ([self isSameDay:notification.fireDate]) {
NSLog(#"Notifcation for today: %#", notification);
return YES;
}
}
return NO;
}
/**
* checks if date matches today by comparing year, month and day
*/
- (BOOL)isSameDay:(NSDate *)anotherDate {
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.timeZone = [NSTimeZone defaultTimeZone];
NSDateComponents *components1 = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]];
NSDateComponents *components2 = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:anotherDate];
return (components1.year == components2.year &&
components1.month == components2.month &&
components1.day == components2.day);
}
I've created a old uilocalnotification, now, I want to update it, I searched on Google but there are no way to update the local notification. So, I decided to cancel it and create a new local notication:
- (void) cancelLocalNotificationByUserInfo: (NSDictionary *)dictInfo
{
UIApplication *application = [UIApplication sharedApplication];
NSArray *notifArr = [application scheduledLocalNotifications];
for (int i=0; i<notifArr.count; i++)
{
UILocalNotification* theNotif = (UILocalNotification *)[notifArr objectAtIndex:i];
if ([theNotif.userInfo isEqual:dictInfo])
{
[application cancelLocalNotification:theNotif];
}
}
}
- (void) addLocalNotification: (NSDate *) fireDate soundName: (NSString *) soundName
alertBody: (NSString *) alertBody infoDict: (NSDictionary *)infoDict
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = fireDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = alertBody;
// Set the action button
localNotif.alertAction = #"Show me";
localNotif.hasAction = YES;
localNotif.applicationIconBadgeNumber = 1;
localNotif.soundName = soundName;
localNotif.userInfo = infoDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
}
But, everytime, I execute the addLocalNotification method, the old local notification is fired immediately. Please help me!