Auto-detect time of day - ios

I'm writing a daily to do list app, and want the app to update certain elements with each new day. This isn't a problem if the user closes the app one day and then reopens it the next -- I just compare days in the startup methods.
However, this is a problem if the user happens to be using the app exactly at midnight. At midnight, daily task elements need to reset themselves automatically for the new day.
Here's my issue -- I could have a constant thread running in the background, always accessing [NSDate date] and checking for a new day. But I feel like there must be a better way, especially because this only has to happen once per day (and then, only if the user is using the app at midnight).
Thank you in advance!

In applicationDidFinishLaunching: and applicationWillEnterForeground:, setup an NSTimer scheduled to trigger at midnight. Also, register for UIApplicationSignificantTimeChangeNotification to reschedule the timer for time zone changes etc.

Related

iOS do scheduled operation in background or when app active

I have CoreData model which I want to update at 12 AM. So it's kind of an even when the app can recognize that a new day is coming and at 12 AM change some things in data models.
Initially, the idea was:
Prepare a single function that returns updated data. So before the function returns smth I every time check for the time (NSDate interval between two dates) and then update data model (if it's a new day). But the architecture not so simple for this purpose and it will take some time to prepare for a single point where I can get updated data, also it takes some time in background to update CoreData model which also adds some expenses to this task.
Is this ok solution to use some timer which will update data at 12 AM, I don't care about consistency in this case, but I don't like a timer which is checking every single second is 12 AM already or not. Is there some push notification update or some scheduler manager in iOS which can update data for me. One more time I just want to update the data layer and I don't care about consistency in UI. If consistency matter for sure then I would like to follow initial ide with a single point of retrieving data.
So I probably need some scheduler manager for this purpose or rewrite code of how I get the data.
There is no way to execute a function at regular intervals, even when the app is backgrounded/killed by the user.
The most reliable solution for executing a function at regular intervals even when the app is backgrounded is to use push notifications scheduled for the specific time intervals (midnight each day in your case), which would wake up the app and let it update its data. However, this solution has its downsides, since you need a server to send the push notification from and the users device needs to be connected to the internet. Also, push notifications don't wake up the app in case the user manually killed it.
For your particular problem, the best solution would be to refactor your code in a way that you have a single function that can be used to retrieve data and hence this function could ensure the data is updated in case a certain time interval has passed since the last update.
You might want to look into BGProcessingTask. You won't have granular control over when you're granted CPU time but you can set the interval you'd prefer that the task execute. Ultimately, when you run and how often is up to the system.
I would recommend checking out the new BackgroundTasks Framework Apple releases for iOS 13.
https://developer.apple.com/documentation/backgroundtasks
While you are not guaranteed at specific time if you have a window (12 am - 3 am) scheduling background tasks may be sufficient for you.

Timer in waiting game like clash of clans in iOS, clock change user proof

I've read this tutorial and this question, but when i use NSDate() or CFAbsoluteTimeGetCurrent() it is easy to trigger by the user setting the clock forward.
If i use CACurrentMediaTime(), the countdown seems not accurate at long time (1 hour or more).
How can I check the passed time correctly?
I must check the time in a server? How?
Thanks
You can use a free service such as http://timezonedb.com/api to get the current time. You just need to register for a free API key. No need to add all the extra time of implementing your own server for a simple task like getting the time

Swift: Creating a repeating local notification between a set time each day

I am trying to create a repeating local notification that will notify the user every hour between a set time every week day (e.g. 9-5 monday-friday) but after searching cant find any documentation on how to implement this.
If you want only 5/7 it can be a problem.
When you schedule a local notification you can also set a calendar unit as -repeatInterval property. This is cool because there is an per-app limit (maybe 64) of maximum number of notification that you can schedule, thus creating one you can fire it each day at the same time.
If you need to create a different kind of repetition is easy to reach that limit, to avoid that you can recreate further notifications each time the user open the app, or if you implement interactive notifications, each time the user interact with one.
Or but I've never tried you can create a notification for each day of the week NSWeekCalendarUnit(except sat and sun) an set the repetition to weekday for each, in this way you will only spend 5 notifications, for infinite repetition.

iOS Time change notification and previous time

I have an application that works with timeout (let's say -> ring in 3 days). My problem occurs if a user change the device local time while being offline because I am comparing two NSDate (the final date and today) to check that timeout.
So I am trying to get notified when a user made a significant time change (several hours or days) in order to update my timers depending on the difference between before and after the update.
I found the UIApplicationSignificantTimeChangeNotification, which does :
Posted when there is a significant change in time, for example, change to a new day (midnight), carrier time update, and change to or from daylight savings time.
That nearly fits but I can't figure out how to get the "old" time in order to get the difference. I can't rely on a webserver neither because the app should be running in offline mode.
Any idea or suggest is welcome ;)
I finally find a way to solve my problem by using the CPU time (which is always constantly increasing except on reboot).
First time the app is launched, I get the Real time and the CPU time.
Then, when I need to check if time has been changed, I just take
the Real time at first, I add to it ( the current CPU time - the CPU time at first).
This give me the correct time.
Note: take care to use the real CPU time, not the one used by timer because it's stop when device go to sleep.
You should store the current time of your device, when your application goes into background. When the application comes into foreground, you should take the current time of your device. Now measure the difference between these 2 dates. If it is less than zero, it means, the user has set the device with previous date and you should throw the error of time out. If the difference is greater than 0, then you should compare current time with actual finish date.
One more indirect way is to start the location tracking of your device. Keep it on even when the app goes into background. When your didUpdateLocation delegate will hit by system, you will receive CLLocation object in argument. This location object is having currentTime details. Compare the time of last location and current location. If it is negative, user has bluffed with time. Its time to take the action.

Perform an action daily at a specified time

In my application I add income and expense data and display it in a home page as a summary. Now suppose I have some fixed expense, which happens daily, that will be automatically added to the expenses at the time which I set. How can I do this?
Use UILocalNotification with repeatInterval property which reschedule the notification with calendar interval. I suggest to go through following apple iOS guideline.
UILocalNotification
Hope, this will help you..
In my opinion, you should use timer or notification only when you are creating a reminder kind of feature.
As per my understanding from your question, I would suggest you following suggestion:
Keep track of last time that the expense was added to your app's local database. You can store this information in database or in user defaults.
On next run of the application, check last entry time and then calculate other entries that needs to be done. If it is daily, it will be the number of days since last entry.
Add the required entries to your database to make your entries consistent.

Resources