我正在制作一个有计时器的应用程序。我计算从给定时间到0的分钟和秒数。当发生这种情况时,我会启动一个警报视图。
我的结构是:
Mainthread方法分配一个新线程并初始化它。 线程的入口点(方法)有一个计时器,它调用一个计算剩余时间的方法,如果时间到了,则显示一个警报视图。
但是,这是正确的吗?因为现在我从另一个线程更新GUI而不是主...这是不对的?我也在这个帖子中显示一个alertview。
我想过制作另一个方法来封装所有用于更新和显示alertview的逻辑,并且在nstimer调用的方法中使用performSelectorInMainThread,但是这是正确的吗?
感谢您的时间。
答案 0 :(得分:4)
假设确定剩余多少时间相当简单,只需在主线程上运行计时器即可。计时器附加到当前的runloop,因此它不会阻塞任何地方,并且它的回调方法不应该花费过多的时间来运行,因此可以很好地更新UI。
- (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];
}
答案 1 :(得分:1)
无需在辅助线程上运行计时器,只需在主线程上创建计时器。您不能从辅助线程更新GUI,是的,您可以使用performSelectorInMainThread,但为什么要这么麻烦?只要将整个事情放在主线程上,只要你的计时器没有“经常”调用,性能就会没问题。