I am making an application that has a timer. I count the minutes and seconds from a given time down to 0. When this happen I launch an alertview.
My structure is this:
Mainthread method allocate a new thread and initialize it. The entrypoint(method) for the thread has a timer which invokes a method for calculating time left, and if the time is up, displays an alertview.
However, is this correct? Because now I am updating GUI from another thread than the main...and that is bad right? And I am also displaying an alertview from this thread.
I thought of making another method that encapsulate all the logic for updating and displaying the alertview and in the method that the nstimer invokes use the performSelectorInMainThread, however is this correct?
Thanks for your time.
Assuming that it's fairly simple to determine how much time is left, just run your timer on the main thread. The timer gets attached to the current runloop, so it's not blocking anywhere, and its callback method shouldn't take an inordinate amount of time to run, and can therefore update the UI nicely.
- (void) initializeTimerWithEndTime: (NSDate *) endTime
{
// call this on the main thread & it'll automatically
// install the timer on the main runloop for you
self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: self
selector: @selector(timerTick:)
userInfo: endTime
repeats: YES];
#if __TARGET_OS_IPHONE__
// fire while tracking touches
[[NSRunLoop mainRunLoop] addTimer: self.countdownTimer
forMode: UITrackingRunLoopMode];
#else
// fire while tracking mouse events
[[NSRunLoop mainRunLoop] addTimer: self.countdownTimer
forMode: NSEventTrackingRunLoopMode];
// fire while showing application-modal panels/alerts
[[NSRunLoop mainRunLoop] addTimer: self.countdownTimer
forMode: NSModalPanelRunLoopMode];
#endif
}
- (void) cancelCountdown
{
[self.countdownTimer invalidate];
self.countdownTimer = nil;
}
- (void) timerTick: (NSTimer *) aTimer
{
NSDate * endDate = [timer userInfo];
NSDate * now = [NSDate date];
// have we passed the end date?
if ( [endDate laterDate: now] == now )
{
// show alert
[self cancelCountdown];
return;
}
// otherwise, compute units & show those
NSUInteger units = NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit;
NSDateComponents * comps = [[NSCalendar currentCalendar] components: units
fromDate: [NSDate date]
toDate: endDate
options: 0];
[self.clockView setHours: comps.hour
minutes: comps.minute
seconds: comps.second];
}