Is there a clock in iOS that can be used that cannot be changed by the user
I am trying to design a system where real-time events happen and I want to synchronise them to a clock. [NSDate date]
would normally be ok but the user could change this and cheat the system. All I need is a clock that I can take relative times from (a 64-bit counter for example) - I don't need absolute time (or time of day etc).
Is there such an API I can use?
EDIT: I would also like to add that this clock needs to be persistent over sessions of the application.
The best monotonically increasing number on an iPhone is mach_absolute_time()
which is a count of CPU ticks since the last reboot. If you would like it in seconds for any reason, it is most easily fetched with CACurrentMediaTime()
.
Using this to create an "always-increment" is pretty easy. On first launch, store the current value wherever you like. When you exit, and periodically, save the offset from that value. When you restart, check the current value; if it is less than your previous base value, replace your base value (there's been a reboot).
All of this of course can be cleared by removing your app unless you store something on the server.
Note that this cannot be used as a strong security measure. There is no way to prevent an authorized user from forging requests. So depending on what you mean by "cheat the system," it may not be a solvable problem. The best you can do is have constant diligence looking for hacks and dealing with them.
If all you need is a clock to measure events as monotonically increasing, you could just get the current system uptime ala clock_gettime(CLOCK_MONOTONIC)
. If restarting the device is a problem, just save the last value used and at next launch use the last saved value as an offset. The Problem here may be that if they actually shut the device off, it won't count that time. But if you're worried about the user speeding up time, they can't do that, only slow it down.
I am using this in our app
+ (NSDate *) getAWSDate
{
NSDate *today = nil;
NSString *dateString = nil;
NSString *awsURL = @"http://s3.amazonaws.com";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:awsURL]];
[request setHTTPMethod:@"HEAD"];
NSHTTPURLResponse *response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error: NULL];
if ([response respondsToSelector:@selector(allHeaderFields)]) {
dateString = [[response allHeaderFields] objectForKey:@"Date"];
dateString = [dateString stringByReplacingOccurrencesOfString:@"GMT" withString:@"+0000"];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss z";
df.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
today = [df dateFromString:dateString];
[df release];
}
return today;
}
I think mach_absolute_time()
may be what you'll want. There is quite a bit of information here: http://developer.apple.com/library/mac/#qa/qa1398/_index.html
It is basically a counter of the number of ticks since the device started. This will be reset on reboot but other than that it is a monotonically increasing counter.
You can keep the last value of the counter around and deal with it if the counter has decreased since the last time (the device was restarted). In this case you can add the last known value to the current value to get a lower bound of the time that has elapsed, all you'd lose is the time between the last session and the device shut down, you would keep the time between the reboot and the next session though.
What I know, that there is no any other method to get correct time. I would use NTP.
Network Time Protocol (NTP) is a networking protocol for synchronizing the clocks of computer systems over packet-switched, variable-latency data networks. More: http://en.wikipedia.org/wiki/Network_Time_Protocol
In one project I'm going to use NTP (tomorrow i quess), but I already did some research:
iOS library: https://github.com/jbenet/ios-ntp - Author notes: The implementation is not a rigorous as described in those RFCs since the goal was to improve time accuracy to with in a second, not to fractions of milliseconds.
For non-commercial project look on: www.packages.ubuntu.com/source/lucid/ntp
C library: www.hillstone-software.com/hs_ntp_details.htm
Documentation: www.nist.gov/pml/div688/grp40/its.cfm