On my story board, I have set up a timer (which updates every 0.01 seconds) and a UIMapView which displays the user's location when the view controller is loaded. However, when this screen loads, the timer lags for a bit until the map is fully loaded. I assume this is because the loading of the map is a blocking function performed on the main thread.
Is there any way to load the map in the background and display it after it has fully loaded while still keeping the timer running?
Probably not. A map view is a view object and view objects are not thread safe.
Note that Apple's docs on NSTimer say:
A timer is not a real-time mechanism; it fires only when one of the
run loop modes to which the timer has been added is running and able
to check if the timer’s firing time has passed. Because of the various
input sources a typical run loop manages, the effective resolution of
the time interval for a timer is limited to on the order of 50-100
milliseconds.
50 ms is .02 seconds. 100 ms is .04. Thus you are not likely to get the accuracy you need.
Related
I am writing an iPhone game. When the user makes his first move a timer kicks of with an interval of 0.01 seconds. A UILabel displaying the time also gets updated every time.
I noticed when testing on an iPod touch 2nd gen and an iPhone 3GS that the iPod was slower (after 20 seconds the iPhone displayed 00:20,00 and the iPod displayed ~00:10,00). Is there a way to make this more reliable? If I'm correct, the NSTimer should run on its ow thread and should not be blocked by user interaction.
JNK
The NSTimer documentation states:
Because of the various input sources a
typical run loop manages, the
effective resolution of the time
interval for a timer is limited to on
the order of 50-100 milliseconds. If a
timer’s firing time occurs while the
run loop is in a mode that is not
monitoring the timer or during a long
callout, the timer does not fire until
the next time the run loop checks the
timer. Therefore, the actual time at
which the timer fires potentially can
be a significant period of time after
the scheduled firing time.
So accuracy can be as bad as 0.1, not 0.01 seconds. Not to mention if your thread is blocked for some reason. So if your firing time is crucial you should be looking at other things. Read this SO post for kick-off. Apple had a metronome sample code (in which, obviously, timing is crucial) but I can't find it just now.
In any case, if you are implementing a timer with NSTimer, you should record your start time. Then, whenever you update your interface, simply take the difference of the current time and your start time (with NSDates).
make sure you're not basing a timer off of sleeps or delays. You should always update a timer based on things like number of clock ticks since program start or current time
sorry I'm not more familiar with your language
You can't rely on a timer to run exactly at the specified time intervals, so the time you are displaying should always be calculated by taking time interval differences. And I doubt that a timer on the iPhone can run every 1 ms, in Quartz it is possible to get a timer call every 16 ms or so, making 60 fps - so scheduling it at 1ms probably means "run as soon as possible", which might be quite different on different hardware.
I'm trying to create my own loadbar; It consists of 5 bars, sliding in from the bottom from the left to the right, then sliding out to the top in the same order. There should be a fixed amount of time (say, 0.2 seconds) between all of them sliding in.
Currently, i'm using a timer to start them one by one, and then let themselves repeat. However, if there's some lag during start or something, they get messed up. The first two or sometimes 3 bars go almost simultaneously, the gap is bigger, just name it and it happened. I currently just set fixed times when each animation should start, but some lag makes them go bogus.
Any given bar moves up in about 0.3 seconds, waits there for 0.2 seconds, then moves further up in 0.3 seconds. They start 0.2 second after their left neighbour, from left to right. Once they started, they just repeat it.
So, what could i use to coordinate them in such a way, that there will always be the same amount of time between them?
Other things i have considered was just using a lot of images (but that will need lots of images i suppose), or using Key Value Observing (KVO) to see when the previous bar is at the desired height.
According to the NSTimer documentation, NSTimer objects are not guaranteed to be realtime accurate on iOS.
A timer is not a real-time mechanism; it fires only when one of the run loop modes to which the timer has been added is running and able to check if the timer’s firing time has passed. Because of the various input sources a typical run loop manages, the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds. If a timer’s firing time occurs during a long callout or while the run loop is in a mode that is not monitoring the timer, the timer does not fire until the next time the run loop checks the timer. Therefore, the actual time at which the timer fires potentially can be a significant period of time after the scheduled firing time.
It's an issue that effects NSTimer as well as OpenGL based games. Michael Daley mentions something similar in his book about how to set things up properly for an openGL based game. I suspect that this is suffering from the same similar situation.
That said, I would suggest preloading those images a adding them to the view just outside the bounds or frame of the visible view before you need then so that they are immediately available when you need them.
Addendum:
After thinking about this, I'm wondering if the C function wait() will help you here. It's a long shot, but perhaps it's worth a try. If not, then the answer may very well be that there is none.
Addendum 2:
I have no idea if this is going to help you either, but I found this page, which discusses pausing a program for less than a second.
I have an IBAction which starts a number of timers.
I would like to have a second or a pause for a certain time. How can I pause execution?
I know of the [self performSelector:#selector(someMEthod:) withObject:someObject afterDelay:1.0];
but how can I just cause a delay without calling anything?
Thanks
You can call sleep() or +[NSThread sleepForTimeInterval:] but please don't do that on the main thread. Pausing execution of the main thread means your app's UI will be blocked for that time and appear to the user as if it had crashed. If you blocked the main thread for more than a few seconds, Apple's watchdog timer would kill your app instantly.
See this blog post by Jeff LaMarche for more on this issue: http://iphonedevelopment.blogspot.com/2010/05/psa-respect-main-thread.html
You don't want to cause a delay without calling anything. It's bad for the UI, and does not fit Cocoa Touch's event driven paradigm.
Cut the routine in which you want to pause into (at least) two parts/halves. Have the first half set up a delayed call to the second half (perform selector with delay, timer, queue, etc.) and then return to the main loop. The OS will call the second part, later, after potentially doing useful stuff in the mean time (giving the user a responsive UI or saving battery life, catching up with background email, etc.)
You may have to learn how to save state between parts (loop variables, etc.), something that some new programmers seem to miss in their learning.
You can use sleep(int_No_of_Sec); // eg. sleep(1);
Making a simple card game, and it it should ok when the user is in control since he will push a button. It will call my method assigned to that button and logic will be performed and screen updated.
But when the players turn ends, and i want the AI to run everything for a few seconds, update the screen with its decisions etc. Handle some logic, call some animation before handing the control back to the user.
Is there a method i can override in my Controller class that which is a subclass of NSObject that gets called every loop or at least 5-10times a second? Or how is it you guys handle this?
Thanks
-Code
It doesn't seem like you want a background thread at all (at least not one you make) or a timer.
What you really want to to is visually animate the AI actions, to that end look at the CoreAnimation stuff, to define animations for AI actions and then play them. You can specify a time period an animation is to take.
Look at this project for examples of animation from the simple to the complex:
http://github.com/neror/CA360
Just create a an NSTimer that calls a tick method at whatever frequency you desire. But keep in mind that NSTimer is not guaranteed to be precise, so in order to avoid gradually accumulating errors, you might want to check how much time has actually passed (e.g. if the timer fires an average of 10 ms late over 500 ticks, code that depends on precise timing will be five seconds off).
I made a game that uses many timers throughout the code. However the timer has to deal with many tasks in such a small amount of time which leads to the problem where there is lag in my game. For example, my timer runs at an interval of (0.05) and it needs to draw and update many of the images on the screen. Is there any way I can distribute the work flow so that the program runs much smoother?
Thanks
Kevin
I would use an NSThread instead of an NSTimer. I have had more success in this area using NSThread because it runs on an independant thread and is not fired off your main ui thread. In the loop for the thread sleep it for 1/20 (your 0.05) of a second. Because the thread is not running on the UI thread all of its tasks should not slow your UI down. However beacsue it is not running on the UI you will have to call performSelectorOnMainThread to get the UI to update from this background thread. I put a lock on my update method (a simple boolean) that says if the last ui update has not happened, just skip this one. then if im running out of processing time i just drop a frame or two here and there. I also do a lot of checking to see if anything has actually changed before i redraw.
Simple solution: Ditch NSTimer.
Move your redrawing code to a single method, then use CADisplayLink. The issue with using your NSTimer approach is that everything is being redrawn too fast or too slow for the screen. By using CADisplayLink, you can synchronize your redraw code to the screen refresh rate. All you need to do then is touch up your code so that it can deal with not being called at a specific time.
And yes, check to make sure you don't need to redraw as Aran Mulholland said above. Just make sure the checks don't take as long as a redraw.
And remember to optimize your code. A lot. Use ivars to access objects, but the whole property (self.myObject =) to set your objects.