The Problem
I am building an app where I am getting real-time data and updating a MKMapView. I get a batch of data every 10 seconds and between data sets from the webs service I am removing older data points while also adding the new ones.
Instead of updating them all at once I want spread out the animation of the new points I get from the data service over that 10 seconds so I create the 'real-time' feel and avoid as many stops and starts as I can.
Everything seems to be working great except the that the NSTimer is always finishing early... way early. It should loop through the new data over 10 seconds but it will typically finish looping through the new data set 4 to 5 seconds earlier then it should.
I have read through a lot of the Apple documentation and StackOverflow questions (below are two good ones for those that may be looking) :)
https://stackoverflow.com/a/18584973 https://developer.apple.com/library/ios/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG8000
But it seems like most of the recommendations are made for gaming apps using CADisplayLink
(but I am not building a gaming app) or that if you need to use a high performance timer that it should not be used continuously.
My timer does not need to be exact but if I could even get it within .5 seconds that would be great without having to add the overhead of some of the other options I have seen.
As always any thoughts / code / or directions you could point me would be greatly appreciated.
The Code
Once I collect the new data into arrays I create the time interval and start the timer with the code below
addCount = -1;
timerDelay = 10.0/[timerAdditions count];
delayTimer =[NSTimer scheduledTimerWithTimeInterval:timerDelay target:self selector:@selector(delayMethod) userInfo:nil repeats:YES];
That then fires this method that animates through adding and removing the my map annotations.
-(void) delayMethod {
addCount = addCount +1;
if (addCount >= [timerAdditions count]) {
[timerRemovals removeAllObjects];
[timerAdditions removeAllObjects];
addCount = -1;
[delayTimer invalidate];
delayTimer = nil;
} else {
[myMap addAnnotation:[timerAdditions objectAtIndex:addCount]];
[myMap removeAnnotation:[timerRemovals objectAtIndex:addCount]animated:YES];
}
}
UPDATE
I tried updating my timer through GCD. And what is odd is that the timing loop works every other dataset. Still do not have it working every tie but for some reason it seems to be tied to resetting the dispatch time or the timer interval.
-(void) delayMethod {
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * timerDelay); // How long
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
addCount = addCount +1;
if (addCount >= [timerAdditions count]) {
[timerRemovals removeAllObjects];
[timerAdditions removeAllObjects];
addCount = -1;
//[delayTimer invalidate];
//delayTimer = nil;
} else {
NSLog(@"Delay fired count %i -- additoins %lu",addCount,(unsigned long)[timerAdditions count]);
[myMap addAnnotation:[timerAdditions objectAtIndex:addCount]];
[myMap removeAnnotation:[timerRemovals objectAtIndex:addCount]animated:YES];
[self delayMethod];
}
});
}