iOS 上不建議在非主線程進行UI操作,在非主線程進行UI操作有很大幾率會導致程序崩潰,或者出現預期之外的效果。
我開始不知道這一點,在子線程中進行了彈窗操作,結果程序就出問題了!
報的錯誤是(EXC_BAD_ACCESS(code=2,address=0xcc),0x1a0ad32: movl 204(%ecx), %edx ),我以為是空指針導致的內存泄露,用了很多方法,但這問題感覺很頑固,困擾了我很多天。
后來有位大牛指點了我,問我是不是在子線程進行這個彈窗操作。。。直到此時我才明白問題出在哪里,問題順利解決。有時候出現bug卻不知道是哪引起的,這時是最糾結的,等明確了問題所在,問題就不是問題了。好了,言歸正傳。
那么在子線程中的UI操作如何處理呢?有兩種方法:
一:在子線程,你需要進行的UI操作前添加dispatch_async函數,即可將代碼塊中的工作轉回到主線程
dispatch_async(dispatch_get_main_queue(), ^{ //更新UI操作 //..... });
dispatch_async函數是異步操作,對於比較耗時的操作也可以這樣處理:
dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 處理耗時操作的代碼塊... //通知主線程刷新 dispatch_async(dispatch_get_main_queue(), ^{ //回調或者說是通知主線程刷新, }); });
dispatch_async開啟一個異步操作,第一個參數是指定一個gcd隊列,第二個參數是分配一個處理事物的程序塊到該隊列。
dispatch_get_global_queue(0, 0),指用了全局隊列。
一般來說系統本身會有3個隊列。
global_queue,current_queue,以及main_queue.
獲取一個全局隊列是接受兩個參數,第一個是我分配的事物處理程序塊隊列優先級。分高低和默認,0為默認2為高,-2為低
二:performSelectorOnMainThread
performSelectorOnMainThread是指在主線程上執行某個方法,比如數據下載后,更新UI界面等操作
例如:在子線程中使用[self performSelectorOnMainThread:@selector(endThread) withObject:nil waitUntilDone:NO];
-(void)setupThread:(NSArray*)userInfor{ [NSThread detachNewThreadSelector:@selector(threadFunc:) toTarget:self withObject:(id)userInfor]; } - (void)threadFunc:(id)userInfor{ NSAutoreleasePool*pool = [[NSAutoreleasePool alloc] init]; //。。。。需要做的處理。 //這里線程結束后立即返回 [self performSelectorOnMainThread:@selector(endThread) withObject:nil waitUntilDone:NO]; [pool release]; }
performSelectorOnMainThread通知主線程執行函數endThread。
再次強調子線程內不要進行任何UI操作,不要刷新界面。如果需要進行這些操作,通過dispatch_async或performSelectorOnMainThread這兩種方法,調出主線程中的方法去執行。