NSTimer vs CACurrentMediaTime()
NSTimer is not a real-time timer. It's not even close, nor does it mean to be. If you're looking at anything faster than about half a second,
NSTimer is the wrong tool. I wouldn't even recommend it for things under a second. For multi-second things, and particularly multi-minute things, when you don't really care exactly when it fires, it's great. I use it all the time.
CACurrentMediaTime() is not a timer. It's a wrapper around the most accurate time function in the system:
mach_absolute_time(). So if you really care what time it is right now, and you'd like that in a human-understandable number,
CACurrentMediaTime() is your function.
mach_absolute_time() will give you a really accurate number, but it's based on the Mach absolute time unit which doesn't actually map to anything pesky humans think in (and every CPU has a different scale). That's why we have
CACurrentMediaTime() to make our lives easier.
NSTimer isn't for real-time, and
CACurrentMediaTime() isn't a timer. What's a game programmer to do?
Grand Central Dispatch includes some one of the best "make this run at about this time" systems we have. It's a Dispatch Source. I say "about this time" because GCD still isn't really "real time" in the way that RTOS guys mean it. But it's realtime enough for game developers. Look for Creating a Timer in the Concurrency Programming Guide. Also take a look at
dispatch_after(), which is good for one-shot "run this after a delay."
Remember, anything that runs on your main thread (the UI thread, where all the drawing is done), is going to share time with everything else on that thread. So often you're going to need to do calculations on a background thread while you handle drawing and user interaction on the main thread. This is the kind of thing that GCD dispatch_queues are designed to help you with. On the other hand, remember that many iOS devices are single-core. So "background thread" is a bit of a misnomer. Only one thing can really run at a time on the CPU. That's why moving things to the GPU is so important (see below).
You may also want to seriously look at systems like cocos2d, which is a very good game engine. It takes care of a lot of these kinds of details for you and lets you focus on the game part.
Staying in Apple frameworks, you should also take a look at Core Animation. If you're moving things around on the screen with timers, you shouldn't be doing that. Core Animation is how you move things around on the screen. It takes care of a lot of details for you, faster and using much less battery than you'd do on your own, and it moves a lot of the work to the GPU (as I mentioned above). It's a bit more designed for UI elements than games, but it can definitely be used to build simple games.
And of course there's GLKit, but that's a whole different thing....
According to the NSTimer documentation
the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds. which is probably why your seeing a variation in the time interval.
What I would suggest doing is change your update interval to 0.016 sec since there is no reason for your game state to update more often than the screen can draw it. Then you can use a CADisplayLink to handle the timing. This should be very accurate since its using the displays refresh rate.