The requirement is that have to detect if the system time of iPhone is changed by user manually. For that I have used
NSNotificationCenter.defaultCenter
This code worked for me in Swift 3
NotificationCenter.default.addObserver(self, selector: #selector(ClassName.timeChangedNotification), name: NSNotification.Name.NSSystemClockDidChange, object: nil)
}
// Method get called user changed the system time manually.
func timeChangedNotification(notification:NSNotification){
print("Device time has been changed...")
}
It's been a while but it might be useful for anyone who will find this question in future like I did today.
You also could use NTP protocol to know real epoch time at the moment when your app enters background / foreground or in didFinishLaunching. This requires the app to be online, though. But it could help in most cases.
There are at least two open-source libraries for iOS and for Android that can help: TrueTime and Kronos.
I've tried 3 options to do this for an enterprise app that I did that requires the time to always be in sync across users. Since we have no control over the users' setting of the device time, I was also face with your predicament:
Option 1 - Using GPS time: I tried getting the GPS timestamp and comparing it with the local device time. It worked in some countries but did not work in others. Other countries return the device time for some reason.
Option 2 - Using a background process to estimate the approximate time. What you do is to get the timestamp, whenever your app goes to the background. Run a timer that fires every 5 minutes (+/- depending on your tolerance). Then calculate the estimated time by adding the 5min ticks that went by to the stored timestamp when your app becomes active. However, this approach can only detect if the time was changed while your app is already running. And not if the time was changed before your app even started.
Option 3 - Using a time-check at the backend. And this is what I ended up doing. I have a small php backend program that returns the UTC time. So every time my app is executed or returns to the foreground, my app will quickly check the time against my time-server. To handle offline cases, I store the last timestamp before the system goes to the background so you can at least check if the date/time was back-dated. Then check again with the time-server when the system goes online.
So far it's the third option that worked for me. But I guess combining 2 and 3 would even make the system more pull-proof.
As per its documentation, NSSystemClockDidChangeNotification
is:
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.
So unless you were expecting the user to change the date or time while your app is running, you're obviously not going to hear anything. Notifications are triggered by events.
iOS doesn't provide you with a way to ask on whose authority the system believes the time and date is the current value — whether it's carrier network time, time server time, user-supplied time or something else. There's no single server time and no way to ask for it. What you want to do cannot be done.