NSSystemClockDidChangeNotification acts weird when app wakes up - ios

In my app I'm registering a NSSystemClockDidChangeNotification notification in AppDelegate method application:application didFinishLaunchingWithOptions:options.
Posted whenever the system clock is changed. This can be initiated by
a call to settimeofday() or the user changing values in the Date and
Time Preference panel. The notification object is null. This
notification does not contain a userInfo dictionary.
Month ago it was working fine, but these days every time I suspend my app, lock my iPhone and leave it 2 minutes to pass, when opening the app, the selector method is called, which is weird to me. I didn't change the system or time, I just let the device idle.
Can anyone help me understand this? I just want to execute some code when the user manually change the system time, just in that case (tried with UIApplicationSignificantTimeChangeNotification but that doesn't help).

Like that: Getting iOS system uptime, that doesn't pause when asleep
But remember, this solution will fail sometimes because of out-of-sync when system tries to update time from NTP server when the Internet connection is not reachable.

This answer is a bit late but this is what the apple support team replied when I ask a similar question:
Part of the question I asked:
Could it be possible for the OS posted [this notification] if the
time/timezone has not changed in the device?
The answer I got from them:
Absolutely [1]. It's common for a notification like this to be posted
redundantly. In some cases it's triggered by a state change you can't
see. For example — and I haven't tested this theory, so it's just an
example of how this sort of thing can come about — this notification
might be posted if the system's giant list of time zone info has
changed. So, the time zone state has changed, but it's not something
that affects your app.
But in other cases, a notification might be truly redundant (-: iOS
is a complex system and in some cases this complex machinery generates
redundant notifications, and there's no need to filter them out
because…
Your app should respond to such notifications be refetching the info
it cares about and updating its state based on that. If this update
is expensive, keep your own copy of the previous state, compare the
current system state to that, and only do the update if the stuff you
care about has actually changed.

Related

Can IOS app do things even when it is not working at all (Killed/Non-running state)

I Did lots of BG tasks in the past, But Trying to get data when app is killed (Even when user is giving Always permission) seems not to work.
I wonder if there is a solution for that.
To make things clear, I am not talking at the moment when app change from Active or Background even to suspended mode. I'm talking about if the user is using the app and set permissions but then kills the app and after that i need every hour to get data from the user and send data to them.
Is there a way to do that?
Can a Today widget help me with that? Does a Today widget "lives" all the time and i can get that from it 24/7?
Whet is working is CLLocation manager. This is working even when the app is killed. But only when the user is changing a location.
I need that to work when the user is in the same place also.
Non of the other methods work. Not BGTask (I need every hour on the hour and not when apple decide to do things), Nor Silent Push Notification for some reason (Regular ones work, but i Don't want to bother the user with a push every hour just for getting and sending data).
Sorry there is no code to show as this is a very general question. But i think that is very important one to many people and can't find an answer for that.

Schedule UILocalNotification based on changes to Core Data

I'm making a simple app with a Today Widget extension that logs events.
The user can tap a button in the app or the related Today Widget to log an event. These events are saved with Core Data any time the button is pressed either place.
Whenever a new event is logged in the app, I run a function called updateLocalNotificationsFromCoreData(). It handles the setup of UILocalNotifications based on the most recent event in Core Data after clearing the appropriate existing notifications.
However, when a new event is logged from the Today Widget, I can't use this function because I need to register the Local Notification with UIApplication.sharedApplication().scheduleLocalNotification(), and UIApplication is not available in the Today Widget extension.
I realize I'll probably need do something unconventional or hacky to get this working, so I'm trying to evaluate possible approaches and come up with a relatively robust solution.
Basically, I want to find a way I can call my
updateLocalNotificationsFromCoreData() function right away any time a new event is logged.
If I can't do it every time an event is logged, an alternative would be to trigger the updateLocalNotificationsFromCoreData() function periodically (somewhat frequently) another way. Here are some solutions I was thinking about using, but I don't like any of them:
Do it in AppDelegate when the app is launched (or another state change)
One approach I'm thinking about is running my updateLocalNotificationsFromCoreData()function in AppDelegate somewhere, like didFinishLaunchingWithOptions.
The downside is that it would require the user to open the app periodically. If the user didn't open it much the notification behavior would be inconsistent. I'd prefer a solution where a user could interact with only the Today Widget and reliably get Local Notifications without ever opening the app.
Sync the events to a server and use Push Notifications
I've thought about syncing the data in Core Data to a server, then setting up Push Notifications to the user's phone based on that.
I don't like this, because I want the user to still be able to get notifications without an Internet connection. It also introduces a lot of extra overhead of syncing the data with a server.
Ping a server, and send a content-available Push Notification
When someone logs an event with the widget, I could ping a server. That server could send back a silent content-available push notification to trigger the app to run updateLocalNotificationsFromCoreData() in the background.
I found a similar question (Scheduling local notification from within a Today extension) where one answer proposes a similar solution. Unlike the previous solution, an Internet connection is not needed to receive the notifications, but an Internet connection would be required to make sure the notifications are up to date when a new event is logged.
Background fetch
I thought about using Background Fetch to fetch something arbitrary from a server, then run the updateLocalNotificationsFromCoreData(). This would be a way to trigger the update in the background, although it seems silly to fetch data if that data isn't being used, and seems like something for which an app could be rejected. There also seems to be a risk of the system not calling the background update regularly if the user doesn't open the app much and mostly uses the Today Widget.
Use background location updates
This seems like the dumbest approach, but I thought I would mention it anyway since I thought about it. I could use one of the low accuracy background location update modes to trigger updateLocalNotificationsFromCoreData().
It would require the user to allow location in the background, which would be hard to explain. And, it would require the user to at least move around a few blocks to trigger the function, which could provide an inconsistent user experience. Also, it would increase power consumption of the app for a silly reason.
I'd really appreciate fresh ideas about how I might be able to reliably schedule local notifications when Core Data changes on a device that doesn't have an Internet connection!
Or, if that doesn't seem possible, I'd appreciated feedback on which approach seems to make the most sense.
EDIT: I came up with a new solution. It's not ideal, but I think it's better than these other approaches I was considering. When someone taps the button to log the event, I launch the full app. It's annoying because I have all the data I need at that point to give the user feedback and log the event within the Today Widget without launching the app, but by launching the app I have the opportunity to check and schedule local notifications.
Also, in iOS 9 the annoyance on the user is slightly minimized because the system-wide "back" button will appear and let the user go back to the previous app easily once my app has launched from the Today Widget.
In the future I may try a solution where one of the server-based approaches above is used when an Internet connection is available, and I would then fall back to this system of opening the app only when the network connection is not available and I need to schedule the local notifications within the app.

Use of "applicationSignificantTimeChange"

May be I am asking a stupid question here.
I recently noticed an UIApplication delegate method
- (void)applicationSignificantTimeChange:(UIApplication *)application {
}
I was wondering what will be its actual use? Do we need to handle this. Can anyone explain a scenario that can happen in an iOS application and we need to do some coding here.
My App is really sensitive to system time, that is the reason I am asking this question. After seeing this API , I have a feeling that I am missing something here to handle.
I am just curious to know... :)
Thanks,
Ramesh Chandran A
Per the documentation on iOS, this method is called:
Examples of significant time changes include the arrival of midnight,
an update of the time by a carrier, and the change to daylight savings
time. The delegate can implement this method to adjust any object of
the app that displays time or is sensitive to time changes. Prior to
calling this method, the app also posts a
UIApplicationSignificantTimeChange notification to give interested
objects a chance to respond to the change. If your app is currently
suspended, this message is queued until your app returns to the
foreground, at which point it is delivered. If multiple time changes
occur, only the most recent one is delivered.
Examples of when this should be used include:
If your app has repeating scheduled events, such as a local notification that now is past, and your app should reschedule the next notification (like daily reminders).
If your app displays data in time ago that needs to be correct, even if the user sets a bad time (for example a medical app that shows your current glucose reading or similar). If a glucose monitor showed an old glucose value as the users current glucose value for instance, the user could make the wrong decision and get hurt.
How you respond to this event depends on your application. You could for instance, read UTC from a server to see if the phone's UTC is correct within some margin, and take appropriate action, such as warning the user, or updating an internal offset between actual UTC and phone UTC.
Hope that helps.
-applicationSignificantTimeChange: is roughly equivalent to the UIApplicationSignificantTimeChangeNotification notification.
I have a custom date picker control that highlights the today date. Subscribing to this notification allows it to change its highlight at midnight, or if the user messes with the time setting manually.

Xcode - Run code each day on 00:00

I need a piece of code for Xcode (obj-c) that runs every day at 00:00.
The reason for this is because my server updates data each new day and I would like my app to synchronize with the update.
I was thinking about doing a timer that runs every minute and checks the time (from internet, not the phones time), but it seems like there could be an more efficient way.
Help or pointers really appreciated!
Thanks
Use the calendar app on your mac. Set up a recurring event every day at 0:00. At the point where you pick the type of alert, you can select an option to open a file (as opposed to a pop-up, etc.). Pick your app as the file to be opened.
When the app becomes active, register a local notification (UILocalNotification) to trigger at midnight.
Then, you can perform the updates at the app delegate's -application:didReceiveLocalNotification:
You can then cancel the notification when the application goes to background by calling the UIApplication's method -cancelLocalNotification:
I don't think it's even required to use notification here. Notification is usually on best effort basis and doesn't guarantee the delivery. This can be done in few simple steps.
Save the lastUpdated time in your iOS app. Probably in NSUserDefaults or if you're using local database you can store it there as well.
Everytime user launches the application check how much time has elapsed since last update.
If it's more than 24 hours then make an API call to your server and check if there's any new updates available (which you can determine probably from server timestamp). Get the latest data (possibly only the delta difference in stead of everything).
Update the lastUpdated time in your iOS app.

iOS: EKEventStoreChangedNotification. When is it sent?

I've got an app that shows calendar events. I want it to update whenever there's a change to the user's calendar in iCloud.
The docs claim EKEventStoreChangedNotification is sent when an event is added/removed/modified. And I have sometimes found that to be the case. But other times, no notification is sent at all. Every three minutes I call [EKEventStore refreshSourcesIfNecessary], but even that won't pick up the change. The only way I can reliably get a change detected in my app is by switching to the Calendar app, waiting for the event change to appear there (normally within a few seconds), then going back to my app…and there it is.
One more thing: I have "Push" notifications turned on my for my iCloud calendars.
Any idea what is going on here? Why is it inconsistent? And how can I make it consistent?
Thanks!
Not sure it helps, but I also hit this issue (just assuming I could rely on the EKEventStoreChangedNotification)... With the approach that you took (calling [EKEventStore refreshSourcesIfNecessary] tho, I do get consistent results, where moments after calling that method, I then receive the notification of changes. Seems to work all the time.

Resources