10

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().addObserver(self, selector: "timeChangedNotification:", name: NSSystemClockDidChangeNotification, object: nil)

and

 func timeChangedNotification(notification:NSNotification){
    println("Device time has been changed...")
    }

But not getting the results. Also if this time is not changed means it is automatic time provided by network then have to compare with server time.How can this be done? Please give help for the same.

TechSavy
  • 797
  • 2
  • 8
  • 22

4 Answers4

7

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.

Tommy
  • 99,986
  • 12
  • 185
  • 204
7
    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...")
    }
Sudhi 9135
  • 745
  • 8
  • 17
6

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.

Rio Bautista
  • 433
  • 5
  • 4
  • There is one problem with the 3rd approach. The app I am working on is time tracking application. If a user kills the app, pulls back the time, records the time in my app, puts the time forward and records the time again. If he turns on the app after second time record. The time stamp stored in the app or server is of no use. As the time is already elapsed and we did not have in sync with server in that time. – Niranjan Molkeri Feb 08 '19 at 18:43
  • hmm how can he "record the time in my app" after he killed the app? or maybe I did not understand the scenario. What he must do is to put the time back before he runs the app again so the app wouldn't know there was a time change. But then that's was the intention after all. In my use case, it's usually caused by users who goes out of the app, play candy crush, mess the time to get more gems, forgets to correct the time and run my app again. – Rio Bautista Mar 22 '19 at 05:59
2

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.

joliejuly
  • 2,127
  • 1
  • 21
  • 24