Multiple Notifications Not Firing - ios

I'm scheduling two notifications as shown below. The app is a long-lived app. One local notification is scheduled to run every hour. The other is scheduled to run once per day. Only the second scheduled notification (the hourly notifcation) fires.
- (void)scheduleNotification
{
LogInfo(#"IN scheduleNotification - DELETEYESTERDAY NOTIFICATION SCHEDULED.");
UILocalNotification *notif = [[UILocalNotification alloc] init];
NSDictionary *deleteDict = [NSDictionary dictionaryWithObject:#"DeleteYesterday"
forKey:#"DeleteYesterday"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[components setDay: day];
[components setMonth: month];
[components setYear: year];
[components setHour: 00];
[components setMinute: 45];
[components setSecond: 0];
[calendar setTimeZone: [NSTimeZone systemTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
notif.fireDate = dateToFire;
notif.timeZone = [NSTimeZone systemTimeZone];
notif.repeatInterval = NSDayCalendarUnit;
notif.userInfo = deleteDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
and then I schedule this after above:
- (void)scheduleHeartBeat
{
LogInfo(#"IN scheduleHeartBeat - HEARTBEAT NOTIFICATION SCHEDULED.");
UILocalNotification *heartbeat = [[UILocalNotification alloc] init];
NSDictionary *heartbeatDict = [NSDictionary dictionaryWithObject:#"HeartBeat"
forKey:#"HeartBeat"];
heartbeat.userInfo = heartbeatDict;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[components setDay: day];
[components setMonth: month];
[components setYear: year];
[components setHour: 00];
[components setMinute: 50];
[components setSecond: 0];
[calendar setTimeZone: [NSTimeZone systemTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
heartbeat.fireDate = dateToFire;
heartbeat.timeZone = [NSTimeZone systemTimeZone];
heartbeat.repeatInterval = NSHourCalendarUnit;
[[UIApplication sharedApplication] scheduleLocalNotification:heartbeat];
}
The above are scheduled when the app launches in the viewDidLoad of the main view controller.
- (void)viewDidLoad
{
[self scheduleNotification];
[self scheduleHeartBeat];
[super viewDidLoad];
//OTHER CODE HERE
}
Then in the appdelegate I have the following:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
LogInfo(#"IN didReceiveLocalNotification NOTIFICATION RECEIVED.");
NSString *notificationHeartBeat = nil;
NSString *notificationDeleteYesterday = nil;
application.applicationIconBadgeNumber = 0;
if (notification) {
notificationHeartBeat = [notification.userInfo objectForKey:#"HeartBeat"];
notificationDeleteYesterday = [notification.userInfo objectForKey:#"DeleteYesterday"];
LogInfo(#"IN didReceiveLocalNotification HEARTBEAT NOTIFICATION TYPE: %#", notificationHeartBeat);
LogInfo(#"IN didReceiveLocalNotification DELETEYESTERDAY NOTIFICATION TYPE: %#", notificationDeleteYesterday);
}
if ([notificationHeartBeat isEqualToString:#"HeartBeat"]) {
//CREATE THE HEARTBEAT
LogInfo(#"CREATING THE HEARTBEAT.");
//CALL THE FUNCTIONALITY HERE THAT CREATES HEARTBEAT.
}
if ([notificationDeleteYesterday isEqualToString:#"DeleteYesterday"]) {
//DELETE YESTERDAYS RECORDS
LogInfo(#"DELETING YESTERDAYS RECORDS.");
}
}
The notification that is scheduled last (scheduleHeartBeat) is the only notification that is fired.
Could somebody help me figure out why this is happening?

You have specified your repeat interval to NSDayCalendarUnit. So, your notification will be fire but at next day at specified time.
For testing purpose change your this repeat interval and check your code is working properly.
I have tested. Your code is working properly here.

Related

Swift 3 - Running a function even when app is in background

I'm facing troubles with my iOS app.
I would like to run a function every day even if my application is not on foreground on my IPhone. I tried to use NSTimer Object but it doesn't work if my app is in background.
How can I achieve this?
Note: My function will trigger a notification which differs based on the current day.
Paulw11 is correct. You can use background refresh and a local notification. The background fetch will be called randomly. Each time it is called the local notification will reset. This code is Obj C, it is a bit old, but the concept is the same.
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
BackgroundFetch * fetch = [[BackgroundFetch alloc] init];
[fetch fetchNewDataWithCompletionHandler:^(UIBackgroundFetchResult result) {
completionHandler(result);
} successDictionary:^(NSDictionary *responseDict) {
// Schedule local notification, in this case it is 9am
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *notif = [[UILocalNotification alloc] init];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[components setDay: day];
[components setMonth: month];
[components setYear: year];
[components setHour: 9];
[components setMinute: 0];
[components setSecond: 0];
[calendar setTimeZone: [NSTimeZone systemTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
notif.fireDate = dateToFire;
notif.timeZone = [NSTimeZone systemTimeZone];
notif.alertBody = [NSString stringWithFormat:#"%#: %#", responseDict[#"city"], responseDict[#"temp"]];
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
You can't do it, because you can't run in the background, and in fact your app might not even be running. So rethink your architecture. For example, set up 30 notifications for the next 30 days, in case your app never runs during that time. That's what a notification is: a message delivered on your behalf by the system, which is always running.

Why my notification is being scheduled 5 hours earlier

I am making an app where I have to schedule local notifications for all the time stamps that is stored in my database when the app will be installed for the first time.
The notifications are being scheduled but when the alarm rings, I realize it is ringing at a time that is exactly 5 hours delayed than the current time. Imagine, I have 3 notifications to go off today- one at 2:11 pm, another at 3:18 pm and another at 8:15 pm. Now, imagine my current time is 7:11pm. I will have a notification go off. which is exactly 5 hours after my first timestamp. Then again it is go off at 8:18 pm.
The following is my code. Can anyone please help.
-(void) setLocalNotification {
TimeCalculationLogic *timeManager = [[TimeCalculationLogic alloc]init];
NSMutableArray *allTimeStamps = [timeManager getAllTimeStamps];
NSDate *currentTime;
for(beginningTime *time in allTimeStamps){
NSDate *currentDate = [timeManager getDateFromString:time.activeDate];
currentTime = [timeManager getDateTimestampFromString:time.first];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
currentTime = [timeManager getDateTimestampFromString:time.second];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
currentTime = [timeManager getDateTimestampFromString:time.third];
[self getComponentToScheduleNotificationFromDate:currentDate andTime:currentTime];
}
NSArray *activeNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// Add back the still relevant notifications
for (UILocalNotification *notification in activeNotifications) {
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
-(void)getComponentToScheduleNotificationFromDate:(NSDate*)date andTime:(NSDate*)timestamp{
self.schedulerComponent = [[NSDateComponents alloc] init];
NSCalendar *calender = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
NSDateComponents *components;
components = [calender components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[self.schedulerComponent setYear:year];
[self.schedulerComponent setMonth:month];
[self.schedulerComponent setDay:day];
components = [calender components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:timestamp];
NSInteger hour = [components hour];
NSInteger minute = [components minute];
NSInteger second = [components second];
[self.schedulerComponent setHour:hour];
[self.schedulerComponent setMinute:minute];
[self.schedulerComponent setSecond:second];
[self.schedulerComponent setTimeZone:[NSTimeZone systemTimeZone]];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
NSDate *setTime = [cal dateFromComponents:self.schedulerComponent];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = setTime;
localNotif.timeZone = [NSTimeZone systemTimeZone];
localNotif.alertBody = #"It's time Again!";
localNotif.alertAction = #"View";
localNotif.soundName = #"ajan.caf";
localNotif.applicationIconBadgeNumber = 1;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}

local notifications issue delivering on ipad vs iphone

I have issues on the local notifications for my app. when I test my app for its notifications, on the iphone it is firing once daily but on the ipad 5x time daily. here's my code :
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:[NSDate date]];
NSInteger day = [comp day];
NSInteger month = [comp month];
NSInteger year = [comp year];
NSInteger hour = [comp hour];
NSInteger min = [comp minute];
NSInteger sec = [comp second];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay: day];
[components setMonth: month];
[components setYear: year];
[components setHour: hour];
[components setMinute: min];
[components setSecond: sec];
[calendar setTimeZone: [NSTimeZone defaultTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
// Schedule the notification
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = dateToFire;
int i = arc4random() % 2;
if (i == 1) {
localNotification.alertBody = #"Collect your FREE coins!";
} else {
localNotification.alertBody = #"It's time to win";
}
localNotification.alertAction = #"View";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[localNotification setRepeatInterval: kCFCalendarUnitDay];
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
NSLog(#"local notif = %#", localNotification);
What is my mistake in this code? why it seems that it correctly gives notification on iPhone but not on the iPad?
If in your iPad OS version > 8.0 then you have to take permission from user. Write below code in "didFinishLaunchingWithOptions" (AppDelegate.m)
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}

How to fire daily localnotification at specific time in iOS

I want to get daily notification and for that I have googled and
I got some solution from this iPhone : Daily local notifications but I couldn't recognise properly
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay: 3];
[components setMonth: 7];
[components setYear: 2012];
[components setHour: 6];
[components setMinute: 0];
[components setSecond: 0];
[calendar setTimeZone: [NSTimeZone defaultTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
Let's say suppose current time is 3:13, and current date is 20-11-2014
in this I want to set local notification at time of 3:14, 20-11-2014 can anybody please help me, because I have tried with following things but not working
[components setDay: 20];
[components setMonth: 11];
[components setYear: 2014];
[components setHour: 15];
[components setMinute: 14];
[components setSecond: 0];
NSDate *date = [NSDate date];
NSDate *newDate1 = [date dateByAddingTimeInterval:60*60*24];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = newDate1;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = [[NSUserDefaults standardUserDefaults] objectForKey:#"NotificationText"];
localNotif.alertAction = #"View";
localNotif.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
try this one hope this may help you. Thank you
NSDate* now = [NSDate date] ;
NSDateComponents* tomorrowComponents = [NSDateComponents new] ;
tomorrowComponents.day = 1 ;
NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDate* tomorrow = [calendar dateByAddingComponents:tomorrowComponents toDate:now options:0] ;
NSDateComponents* tomorrowAt7AMComponents = [calendar components:(NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:tomorrow] ;
tomorrowAt7AMComponents.hour = 7 ;
NSDate* tomorrowAt7AM = [calendar dateFromComponents:tomorrowAt7AMComponents] ;
localnotification.fireDate = tomorrowAt7AM;
I hope this helps you.

How To Distinguish Between Local Notifications

I have implemented local notifications in a long-lived app. The app runs 24 hours per day in kiosk mode. One of the local notifications fires once per day and the other fires once per hour. The notification that fires once per day deletes all local core data information from the previous day. The notification that fires once per hour is a "heartbeat" for the app and creates a check in on the server once per hour.
Here is the schedule for the hourly heartbeat (it is in my main viewcontroller):
- (void)scheduleHeartBeat
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *heartbeat = [[UILocalNotification alloc] init];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
[components setDay: day];
[components setMonth: month];
[components setYear: year];
[components setHour: 00];
[components setMinute: 10];
[components setSecond: 0];
[calendar setTimeZone: [NSTimeZone systemTimeZone]];
NSDate *dateToFire = [calendar dateFromComponents:components];
heartbeat.fireDate = dateToFire;
heartbeat.timeZone = [NSTimeZone systemTimeZone];
heartbeat.repeatInterval = NSHourCalendarUnit;
[[UIApplication sharedApplication] scheduleLocalNotification:heartbeat];
}
I call the above method in viewDidLoad.
Then in my AppDelegate I have the following:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
application.applicationIconBadgeNumber = 0;
[[OLEngine myEngine] deleteStuffFromYesterday:#"MyObject"];
}
In the didReceiveLocalNotification I need to distinguish between which Local Notification has been fired because I do not want to call the method deleteStuffFromYesterday every hour - only once per day.
How can I distinguish between these scheduled local notifications in my app delegate code?
You can use the userInfo Property to store an NSDictionary for this.
Store the info:
localNotification.userInfo = #{ #"myCustomType" : #"heartbeat" };
Retrieve the info:
NSString *myCustomType = localNotification.userInfo[#"myCustomType"];

Resources