2011-08-28 59 views
2

MyThreadRun方法是從的MyMethod調用這樣PerformSelector不工作

NSArray* args = [NSArray arrayWithObjects:arg1, target, NSStringFromSelector(mySelector), nil]; 
NSThread* mythread= [[[NSThread alloc] initWithTarget:self selector: @selector(MyThreadRun:) object:args] autorelease]; 
[MyThreadRun start]; 

在MyThreadRun結束後,我嘗試調用函數中呼籲的MyMethod啓動線程開始與階級,像這樣:

NSObject* callbackTarget = [args objectAtIndex:1]; 
NSString* selector = [args objectAtIndex:2]; 
[callbackTarget performSelector:NSSelectorFromString(selector) withObject:calculationResult afterDelay:0]; 

我對選擇所指向的方法一個破發點,而這是從來沒有擊中。

如果我硬編碼方法的名稱,這樣

[callbackTarget updateWithResult:calculationResult] 

它工作正常。

有什麼我需要知道關於performSelector?

回答

22

performSelector:withObject:afterDelay:被調用的上下文是罪魁禍首。這是發生了什麼。

performSelector ...家族的一些成員,像這樣,不會馬上執行選擇器;他們會在當前運行循環中排隊調用,以便在您的fn返回後執行下一輪運行循環。根據蘋果的說法:「指定延遲0不一定會導致選擇器立即執行,選擇器仍在隊列的運行循環中排隊並儘快執行。」

通常這是很好的和預期的。但是你的代碼在你手動啓動的線程上調用它......而這些線程不會像主線程那樣反覆地運行它們的循環。他們調用創建時指定的選擇器一次,然後退出。所以:你的代碼將對你的回調選擇器進行調用,但是這個線程退出;並且它的運行循環不會運行...所以你的排隊調用不會發生。

您可能需要的是performSelectorOnMainThread:withObject:waitUntilDone:,因爲您可能希望首先調用MyMethod方法的線程(可能是主線程)發生回調。

更一般地說,線程是非常棘手的東西。我強烈建議您檢查一下NSOperationQueue,NSBlockOperation以及相關技術 - 它們可以消除很多痛苦。

+0

希望我可以接受2個答案 – Haoest

4

NSString* selector = [args objectAtIndex:2]; 

等於updateWithResultupdateWithResult:

他們是兩種不同的方法。你想要冒號的那個。

+0

調試器顯示它以冒號結尾。無論如何,該字符串值是用NSStringFromSelector編碼的,我相信字符串形成正確。 – Haoest

2

刪除「afterDelay:0」並且您的代碼有效。另外「[MyThreadRun start]」應該是「[mythread start]」。

+1

用[mythread start]很好的觀察,但你說得對,afterDelay是問題所在。我的理論是,afterDelay參數將該方法放入一個隊列中,當該線程結束時,該隊列就消失了。我甚至試圖把(1);在該方法的最後只是爲了保持線程活着,但也沒有工作。刪除afterDelay工作。謝謝。感謝xcode的intellisense,我失去了大約3個小時的抓頭。 – Haoest