I know that there is a method [NSDate date] which returns current date and time from iPhone clock. But if this clock time was changed manually it would rune my code.
Is there any opportunity to get world time, not current time from iPhone?
Yes, you can have correct current time by using ntp/sntp.
Following uris might help you to write your own implementation:
Simple NTP client for iOS : http://code.google.com/p/ios-ntp/
NSDate from time server: http://pathoneycutt.com/2010/12/nsdate-from-time-server/
Related
I am developing an iOS application for iPod Touch in which my application displays the server time always. I always sync the application time with server time whenever the application comes to foreground by making a web service call to the server. If there is a connectivity loss between my server and client for few hours I wont be able to sync the application time. I read iOS does not support running a timer when the application is in background other than few limited cases mentioned below:
Apps that play audible content to the user while in the background, such as a music player app
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Newsstand apps that need to download and process new content
Apps that receive regular updates from external accessories
So how can I keep track of application time? Whenever the user switches to my application he needs to look at the server time so I need to run a timer to update the last synced server time.
A combination of other answers, create a class in charge of obtaining the server time and maintaining the last time the application was synced to the server using a combination of NSDate* lastSync and applicationDidBecomeActive. For example:
-(void)applicationDidBecomeActive:(UIApplication*)application {
[ServerTimeSync sharedInstance] resync];
}
ServerTimeSync will maintain an NSDate* property with the last sync time (you'll want to convert what the server gives you to an NSDate*).
You can store the NSDate when the app goes into the background. When it resumes, get the current NSDate again, and add the difference to your stored server time.
You don't need a timer for this at all.
I would suggest that when you sync time with your server, you have it return its current UNIX timestamp. You can then do:
[[NSDate date] timeIntervalSince1970];
...to get the device's current UNIX timestamp. Then what you can do is store the difference between these two timestamps. This is the clock skew between the server time and the device time.
You can now compute the server's approximate time by taking the device's current UNIX timestamp and adding the clock skew to it. Adjust for time-zone when displaying it (if you want), and you're done. Whenever you sync time with the server, you can just refresh the stored clock skew value.
If you want to get fancy, you can also attempt to measure and take network latency into account when determining the clock skew.
This approach should work much better than trying to store the server's absolute timestamp and then track how much time has elapsed using a timer (or any other mechanism).
I'm making a game like the game Evony for iPhone but instead of being an MMO it is single player. For those of you that don't know about Evony, in the game you upgrade your own buildings and the buildings take a certain amount of time in real life to upgrade. Evony runs off a server but I want my iPhone game to run off of the app. Which leads me to my problem of the game needing to continuously update the time while not running. I'm new to using the clock system in programming and was wondering if any of you could help me.
When the building object is created, mark it with a created time stamp. Then, whenever the view is loaded, or it awakes, compare the current date and time to the created time stamp, giving you the 'lifetime' of the building.
Here is how to get the current date and time in iOS sdk:
[NSDate date]
after i get current device time by using [NSDate date], how do i know it's daytime or night now?
thanks in advance!
To be absolutely certain, I'd use a weather API like Yahoo's weather. Send the current location to the API, and you'll get back some data that contains the sunset and sunrise times for that area.
If the current time is past the sunset time... blammo.
I am interested in building a Timer Based game such as mafia wars or soemthing like that. I'm stuck on one question.
What would be the best way to retain a timer, even if the app is closed?
Should I do this based on the Device Clock? or should I set a time to a server, and get the time when the device starts up?
If any one knows a better way for this,
let me know.
Thanks.
#lessfame
I'll interpret your question as "What's the best way to measure elapsed time between app launches?" instead of "How do I make a timer fire when my app is closed?".
There's no reliable and accurate way to measure time when the device is powered off (remote servers might not be reachable, astronomical measurements might not be possible if it's cloudy, ...). Don't bother.
That said, most CF/NS APIs use CFAbsoluteTime/NSDate (namely, CFRunLoopTimerGetNextFireDate() and -[NSTimer fireDate]). I'm not sure what they do if the system clock changes.
You can use mach_absolute_time() (and it's used internally by some things), but that's just system uptime, so it fails if the phone reboots. I'm not sure if you can get the boot UUID in order to find out if the phone has rebooted.
At the end of the day, CFAbsoluteTimeGetCurrent() or (equivalently) [NSDate date] is probably enough; just make sure that your app behaves sensibly if the time suddenly changes by a day or two in either direction.
Yes, the user can game the system by setting the system clock. You can mitigate this to some extent by occasionally syncing with the server, and keeping track of game time elapsed between syncs. If the difference between elapsed game time and server time is small, then just speed up or slow down the game appropriately to bring elapsed "game time" to real time. If the change is large, you can restore from the last save point on the server, or make the user wait until the elapsed game time has elapsed in server time, or a bunch of other things. This means you can't start playing until the initial sync, but the user has to be online to download the app anyway, so it's not a major problem.
If you only need to retain the time and show how much time elapsed since the game was closed (i.e. you don't need to notify the user when the time is up), you can use the [NSDate timeIntervalSinceNow] method to determine the amount of milliseconds that passed between two times.
If you are saying you want to just know time elapsed since some event, all you do is log the initial time, and then log the final time and compare the difference.
If you need a countdown timer to some event then what you do is set up a local push notification set to go off at the end time.
I need to ensure that my app gets the correct time, not the time set by the user in settings.
So for instance, once the user starts the app, I'd want to get a timestamp. The user would see the elapsed time on a timer on screen updated every second. When the user exits the app, and after some time restarts the app , the timer would just get the current time and compare it with the original timestamp it kept. So basically, just like the stopwatch in the Clock.App on iPhone.
Now the problem with the clock.app is that if the user goes and advances the time in Settings by one hour, this will influence the timer. Obviously I don't want that, because in my app, that would be cheating.
I'd need to get a more trustworthy time source to compare to.
I could get the time from the internet. But the problem is that I'd need internet connection , so only works on if there is an internet connection. My app needs to work offline preferably.
Is there some kind of internal clock I can access?
Is there a way of checking whether the user has changed the date time in Settings?
Any other ideas?
Thanks
Get the time from NIST with the Daytime Protocol:
UDP Based Daytime Service
A server listens for UDP datagrams on UDP port 13. When a datagram is received, an answering datagram is sent containing the current date and time as a ASCII character string (the data in the received datagram is ignored).
NIST Format of response: JJJJJ YR-MO-DA HH:MM:SS TT L H msADV UTC(NIST) OTM
http://tf.nist.gov/service/its.htm
http://tf.nist.gov/tf-cgi/servers.cgi
The best solution I've come up with is using the mach timer which counts time units since last iphone boot.
This works great. The only restriction is that the user cannot be allowed to reboot or it would invalidate his time.
I detect a reboot by initially storing the iphone timestamp associated with the mach timer and then checking every time the app starts, so it hasn't changed. This has as a side effect that if the user changes iPhone DateTime while he's being timed , that will also invalidate the score, but that is ok.
How can I detect whether the iphone has been rebooted since last time app started
I can easily warn my users about this: rebooting or changing iphone time while you're on the clock will invalidate your scored time.
I just posted the following here:
This works to get the GPS time:
#import <CoreLocation/CoreLocation.h>
CLLocation* gps = [[CLLocation alloc]
initWithLatitude:(CLLocationDegrees) 0.0
longitude:(CLLocationDegrees) 0.0];
NSDate* now = gps.timestamp;
It doesn't seem to be tamper-proof though.
I tried this code on an iPhone 4 in airplane mode (iOS 6.1), and even then it gives a time all right. But unfortunately this time seems to change with the system clock. Ugh.
Funny thing that I found (still in airplane mode) is that if you tamper with the system clock (after turning to off Time & Date's Set Automatically), and then turn Set Automatically back to on, the machine restores the real (original) time without a hitch. this works even after cycling the phone's power. So it seems that there is something like a tamper-proof time the device maintains internally. But how to access this?
This method will find the actual current time, found in google.com's response header:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL URLWithString:#"http://google.com"]];
[request setHTTPMethod:#"GET"];
NSHTTPURLResponse *httpResponse = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&httpResponse error:nil];
NSString *dateString = [[httpResponse allHeaderFields] objectForKey:#"Date"];
NSDate *currentDate = [NSDate dateWithNaturalLanguageString:dateString locale:NSLocale.currentLocale];