-1

I have an array of hours hoursArray and array of minutes minutesArray and I am getting the current date from the system now I have the arrays who have the elements of the current month it means if there are 30 days in April there will be 30 hours/minutes in hoursArray/minutesArray which I have inserted in the arrays, and I am getting current date as an index of arrays.

What I have done is that notifications triggers in current day but it does not trigger the next day until I use app daily because when I use app daily before the trigger time method will be called when I turn to background mode and notification rings.

Now I want the notifications should be triggered automatically when date changes, even when I don't use the application for somedays, these all stuff should be in didEnterBackground... method of appDelegate

I have followed this answer, but it is used for same time daily But I want different time daily from arrays based on Current date's index of arrays (it means the current day e.g today is 19 April the index of hours and minutes array should be 19).

Here is how my arrays look like

Hour array = [9, 10, 11, 13, 14, 11, 17, 2, 15, 5.... and so on]

Minute array = [23, 00, 04, 58, 59, 12, 01, 33,.... and so on]

method call in appdelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application
{     
 [self.viewController triggerAutomaticallyDaily];
 [self applicationSignificantTimeChange:application];
 [self refreshAlarm];
}

method inside viewcontroller.m

-(void)triggerAutomaticallyDaily {
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar] ;
NSDate *now = [NSDate date];

NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth |  NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:now]; 
[components setHour:hoursArray[currentDay]]; //currentDay the todays date is 16 I am getting current date from system.
[components setMinute:minutesArray[currentDay]];

UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.fireDate = [calendar dateFromComponents:components];
notification.repeatInterval = NSDayCalendarUnit;
[notification setAlertBody:@"This is your task time"];
// notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:notification]; 
}

Significant time changes after each midnight, method in Appdelegate

-(void)applicationSignificantTimeChange:(UIApplication *)application {
[self.viewController triggerAutomaticallyDaily];
}

Refresh Alarm method in Appdelegate

- (void)refreshLabel
{
//refresh the alarm on the main thread
dispatch_async(dispatch_get_main_queue(),^{      
[self.viewController triggerAutomaticallyDaily];
});
// check every 10000s
[self performSelector:@selector(refreshLabel) withObject:nil afterDelay:10000]; 
}

Have a look at didEnterBackground... when I quit my app the notication method will be called just once. isn't is?? and how the daily notification can I receive when I don't even open the app for a week but I want to get notifications, How method will be called? is method called every time in background mode?

Is there any way so I can schedule the notification and and when the first notification done the second should be triggered and if second done then third should be triggered and so on in the background mode even I don't open the app for a week?? the notifications should be triggered based on current date and time given in arrays.

UPDATE I have even placed the refresh function which refreshes the trigger after each and every 10000 seconds but it is not working.

I have also added significantTimechanges , if there is midnight changes but its not working to here is how I have defined that all.

iOS Developer
  • 311
  • 4
  • 25
  • How many days data you have? Next time when will you call your service to refresh the data as there is no date specified in the response. – TheTiger Apr 19 '18 at 06:49
  • @TheTiger I have months data and the days will be valid unto a month – iOS Developer Apr 19 '18 at 06:50
  • You mean you have 31 days data for March and 28 days data for February? – TheTiger Apr 19 '18 at 06:51
  • How much data you have? There are infinite months --> years to go. – TheTiger Apr 19 '18 at 06:52
  • First of all **If user doesn't open the app then you can't do anything so forget about this achievement.** This type of cases should be handle on server side, so better to go with push notifications instead of local. – TheTiger Apr 19 '18 at 06:58
  • yes 31 data for march and 28 for feb, but I want to achieve in local notifications instead of push, any logic? should I implement with database like sqlite I should store the record for a month so that the data should be handled accordingly from sqlite or any idea – iOS Developer Apr 19 '18 at 07:16
  • `sqlite` will not help you on daily basis, your code will work if app is running. – TheTiger Apr 19 '18 at 07:25
  • Also `these handling should be in didenterbackground...` its not possible so you will not get any answer which will maintain this condition. Hope you know well when `didEnterBackground` get called. – TheTiger Apr 19 '18 at 07:28

3 Answers3

0

Just use below statement instead of NSCalendar

UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.fireDate = [[NSDate date] dateByAddingTimeInterval:(hours*3600)+(Mins*60)];

//Unit of time interval should be in Second

notification.repeatInterval = NSDayCalendarUnit;
[notification setAlertBody:@"This is your task time"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification]; 
Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65
  • Dear I have tried lets see tomorrow if it happen automatically, hope it will be good. – iOS Developer Apr 16 '18 at 12:58
  • You could test it with a shorter interval, so you don't have to wait a day. – koen Apr 16 '18 at 13:01
  • @Koen But I want daily timing should be repeated? is that possible? – iOS Developer Apr 17 '18 at 04:39
  • Just change device time to your target time. Then notification automatically appears. – Hitesh Surani Apr 17 '18 at 05:17
  • @iMHitesh Have a look at updated question when I quit my app the notication method will be called just once. isn't is?? and how the daily notification can I receive when I don't even open the app for a week but I want to get notifications? – iOS Developer Apr 17 '18 at 10:18
  • There is no way schedule notification without opening App. You have to schedule notification for features purpose. – Hitesh Surani Apr 17 '18 at 10:23
  • you can schedule 256 notification at time. So Schedule 256 notification when app in background. – Hitesh Surani Apr 17 '18 at 10:24
  • Oops! I s there any way so I can schedule the notification and and when the first notification done the second should be triggered and if second done then third should be triggered and so on in the background mode even I don't open the app for a week?? – iOS Developer Apr 17 '18 at 11:20
  • This is not working my bro? I can't get daily notifications until I open the app, is there anything in iOS that I want.??? – iOS Developer Apr 18 '18 at 05:06
0

Important Note: Developer can not do anything if application is in kill state or in background for a long time. So this can not be done.

There are many questions for your requirement:

1.1: How many days data you have in one service, for a month, for a year or ?

1.2: Why not push?

1.3: Why do you want to schedule local notification on daily basis while you can schedule many at once?

1.4: There is no way to make changes in the app when its not opened (killed by user) so you can not do anything in that case.

Now come to what we can do:

2.1: Considering you are getting monthly data. So you should schedule all the local notifications at once in for loop by increasing the day component and setting the corresponding time (from your arrays by day index). And its your luck if user opens the application once in a month (90% chances he will) then you can request to server for next month data and do the same.

2.2: Why not this is being handled at server end and use push notifications instead of local. Server guys can configure a cron job for every minute which will fetch the all hours and minutes for users and will send the push.

My suggestion not to go with local but all maximum you can go with 2.1 (schedule all month notifications at once).

TheTiger
  • 13,264
  • 3
  • 57
  • 82
  • 1.1, currently I have a moths data say 30 data for 30 days of April or I can store a years data 365 data and count the current number of the day of the year by current date – iOS Developer Apr 19 '18 at 09:12
  • 1.2 I want want to setup server side stuff so I don't use push – iOS Developer Apr 19 '18 at 09:13
  • 1.3 because I can not store the whole years notifications or so and my data currently is in static arrays then I use the json file to get data from json and what if user changes in json data from setting or increase the time of notifications it will be weird to fire all simultaneously – iOS Developer Apr 19 '18 at 09:15
  • 1.4 can I use completion handlers?? or when notification fires then other notification should be called – iOS Developer Apr 19 '18 at 09:16
  • @iOSDeveloper Please respond all with keeping in mind **you can not do anything if app is killed.** – TheTiger Apr 19 '18 at 09:45
  • If json file got change you can do one thing. In `applicationDidBecomeActive` or `applicationDidFinishLaunching` method you can call the service again, cancel the all schedule notifications and schedule them again. – TheTiger Apr 19 '18 at 09:47
  • But I can call a completion handler and that completion handler will call a function, and inside that function the same completion handler should be called and so on so that when I notification triggers the next should be fired in completion handlers function. is that possible?? – iOS Developer Apr 19 '18 at 10:08
  • By analysing this answer of question https://stackoverflow.com/questions/8393138/objective-c-callback-handler I guess I do that and method after a method will be called.. – iOS Developer Apr 19 '18 at 10:13
  • And where is it mentioned that it will work in kill state too? This is just a normal callback function what it does with your case? – TheTiger Apr 19 '18 at 10:14
  • it is not stated but the method this man is calling in the completion handler while in my trigger notification the completion handler is nil so can I do something?? – iOS Developer Apr 19 '18 at 10:16
  • All things will work if user is using the app no magic will happen here to make the changes in closed app. – TheTiger Apr 19 '18 at 10:17
  • But what you can assume if completion handler can be called continuously – iOS Developer Apr 19 '18 at 10:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169318/discussion-between-thetiger-and-ios-developer). – TheTiger Apr 19 '18 at 10:22
0

As others have said, the better technique is to schedule all of the notifications at once. This is what I do. However, there is a system limit of 64 pending local notifications. In your case, the scheduled notification should trigger every day for 64 days. I have a more difficult problem because I need to schedule notifications every 15 minutes. So, if my users don't respond within 16 hours, they will not get further notifications (64/4 = 16). Also, note that UILocalNotification is deprecated, so you should use UNNotificationRequest. Note that the identifier in UNCalendarNotificationTrigger must be unique for each request.

    content.categoryIdentifier = @"com.nelsoncapes.localNotification";
    NSDate *today = [NSDate date];
    NSDate *fireDate = [today dateByAddingTimeInterval:interval];
    // first extract the various components of the date
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSInteger year = [calendar component:NSCalendarUnitYear fromDate:fireDate];
    NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:fireDate];
    NSInteger day = [calendar component:NSCalendarUnitDay fromDate:fireDate];
    NSInteger hour = [calendar component:NSCalendarUnitHour fromDate:fireDate];
    NSInteger minute = [calendar component:NSCalendarUnitMinute fromDate:fireDate];
    NSDateComponents *components = [[NSDateComponents alloc]init];
    components.year = year;
    components.month = month;
    components.day = day;
    components.hour = hour;
    components.minute = minute;
…
// construct a calendarnotification trigger and add it to the system
    UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier: identifier content:content trigger:trigger];
    [center addNotificationRequest:request withCompletionHandler:^(NSError *error){
        if(error){
        NSLog(@"error on trigger notification %@", error);
        }
    }];
Nelson Capes
  • 411
  • 3
  • 12