Trigger local notifications automatically daily on dynamic time given in arrays Objective c ios
Asked Answered
M

3

-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.

Marius answered 16/4, 2018 at 12:21 Comment(8)
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.Meingolda
@Meingolda I have months data and the days will be valid unto a monthMarius
You mean you have 31 days data for March and 28 days data for February?Meingolda
How much data you have? There are infinite months --> years to go.Meingolda
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.Meingolda
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 ideaMarius
sqlite will not help you on daily basis, your code will work if app is running.Meingolda
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.Meingolda
M
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).

Meingolda answered 19/4, 2018 at 7:19 Comment(13)
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 dateMarius
1.2 I want want to setup server side stuff so I don't use pushMarius
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 simultaneouslyMarius
1.4 can I use completion handlers?? or when notification fires then other notification should be calledMarius
@iOSDeveloper Please respond all with keeping in mind you can not do anything if app is killed.Meingolda
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.Meingolda
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??Marius
By analysing this answer of question #8393638 I guess I do that and method after a method will be called..Marius
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?Meingolda
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??Marius
All things will work if user is using the app no magic will happen here to make the changes in closed app.Meingolda
But what you can assume if completion handler can be called continuouslyMarius
Let us continue this discussion in chat.Meingolda
F
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]; 
Fearnought answered 16/4, 2018 at 12:52 Comment(9)
Dear I have tried lets see tomorrow if it happen automatically, hope it will be good.Marius
You could test it with a shorter interval, so you don't have to wait a day.Celestial
@Koen But I want daily timing should be repeated? is that possible?Marius
Just change device time to your target time. Then notification automatically appears.Fearnought
@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?Marius
There is no way schedule notification without opening App. You have to schedule notification for features purpose.Fearnought
you can schedule 256 notification at time. So Schedule 256 notification when app in background.Fearnought
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??Marius
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.???Marius
M
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).

Meingolda answered 19/4, 2018 at 7:19 Comment(13)
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 dateMarius
1.2 I want want to setup server side stuff so I don't use pushMarius
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 simultaneouslyMarius
1.4 can I use completion handlers?? or when notification fires then other notification should be calledMarius
@iOSDeveloper Please respond all with keeping in mind you can not do anything if app is killed.Meingolda
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.Meingolda
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??Marius
By analysing this answer of question #8393638 I guess I do that and method after a method will be called..Marius
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?Meingolda
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??Marius
All things will work if user is using the app no magic will happen here to make the changes in closed app.Meingolda
But what you can assume if completion handler can be called continuouslyMarius
Let us continue this discussion in chat.Meingolda
R
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);
        }
    }];
Robertson answered 1/7, 2018 at 18:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.