iOS:在NSThread中运行计时器导致的EXC_BAD_ACCESS?

时间:2011-10-17 01:07:48

标签: ios xcode exc-bad-access nsthread nsrunloop

我的应用中遇到了一些崩溃。当检查日志并使用atos时,它告诉我确切的崩溃位置,这是我告诉我的NSRunLoop运行的地方:

/**
 * Create a new thread for the timer
 *
 * @version $Revision: 0.1
 */
- (void)createTimerThread {
    NSThread *timerThread = [[NSThread alloc] initWithTarget:self selector:@selector(startTimerThread) object:nil];
    [timerThread start];
    [timerThread release];
}//end


/**
 * Start the actual timer
 *
 * @version $Revision: 0.1
 */
- (void)startTimerThread {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

    // Start timer
    self.countTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateCounter:) userInfo:nil repeats:YES];

    [runLoop run];// <--- Crash happened here
    [pool release];

}//end


/**
 * Update the counter
 *
 * @version $Revision: 0.1
 */
- (void)updateCounter:(NSTimer *)theTimer {

    // Does tons of timer stuff here

}//end

正如您所看到的,崩溃发生在[runLoop run],但我不明白为什么。它通常是我第二次调用createTimerThread方法。

我在这里做错了什么?我想要做的只是在后台运行一个计时器,因此它不在主线程上,因为我需要更新UILabel

我应该使用像Grand Central Dispatch(GCD)这样的新东西吗?

2 个答案:

答案 0 :(得分:1)

你说updateCounter正在更新UILabel,并且正在后台线程上运行的计时器中调用它。你不能这样做,你需要在主线程上更新UI视图。

您可以使用performSelectorOnMainThread或GCD(调度到主队列)。我在这篇SO帖子中使用样本进行了比较:

GCD, Threads, Program Flow and UI Updating

这篇SO文章专门提供了一个带GCD的bg计时器示例:

iOS4 Create Background Timer

查看mrwalker的帖子

答案 1 :(得分:0)

任何涉及UI的调用都是线程安全,这意味着您必须对主线程进行任何更新。

不确定您实际想要实现的目标。如果你在每个定时器“tick”上做一些计算上昂贵的东西,那么是的GCD将是你最好的利用块。

也许你可以给我们一些洞察你每次打勾的内容以及你在UILabel中展示的内容?