2011-08-28 60 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