2011-10-17 38 views
0

我一直在我的應用程序崩潰。當檢查日誌和使用ATOS,它告訴我,正是我得到的崩潰,這是我告訴我的NSRunLoop運行:iOS:在NSThread中運行定時器導致EXC_BAD_ACCESS?

/** 
* 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)這樣的新東西嗎?

+0

啓用NSZombies,然後你會發現原因。 EXC_BAD_ACCESS是關於一些被釋放的東西,這不應該是a.k.a殭屍。 –

+0

你是否從後臺線程訪問你的UILabel?或者其他任何UI元素? – JustSid

+0

我更新updateCounter方法中的UILable。所以,不知道現在是否在後臺。 –

回答

1

你說updateCounter正在更新一個UILabel,這是從後臺線程上運行的計時器調用的。你不能這樣做,你需要在主線程上更新UI視圖。

您可以使用performSelectorOnMainThread或GCD(派發到主隊列)。我比較了這一點使用試樣均SO交:

GCD, Threads, Program Flow and UI Updating

這SO本文專門具有BG計時器與GCD一個例子:

iOS4 Create Background Timer

看從mrwalker

+0

謝謝,將我的UILabel的更新移到另一個由performSelectorOnMainThread調用的方法。 –

0

任何涉及UI的調用都是而不是線程安全,這意味着您必須對主線程執行任何更新。

不知道你實際上試圖達到什麼。如果你在每個計時器上做一些計算花費很高的「打勾」,那麼肯定GCD是你最好的選擇。

也許你可以給我們一些見解,說明你在做什麼,以及你在UILabel中顯示什麼?

+0

它只是一個簡單的計時器,從0開始計數。它更新UILabel以顯示已經過了多少時間。每次創建新的核心數據記錄時都會創建計數器。 –

+0

那麼每個核心數據實體實例都有它自己的計時器?也許更好的方法是在每個實體實例上設置「startTime」瞬態屬性。然後設置一個穿過每個實體的計時器,計算經過的時間並更新UILabel。 – cocoahero