使用_cmd在目标c中的主线程上执行方法

时间:2012-11-02 06:14:17

标签: objective-c ios cocoa nsthread foundation

我遇到了这个_cmd技巧:

-(void)methodToBeRunOnMainThreadWithObj:(id)object {
    if (![NSThread isMainThread) {
        [self performSelectorOnMainThread:_cmd withObject:object]
    } else {
        // ... method body
    }
}

这是确保在主线程上执行方法的可靠方法吗?

2 个答案:

答案 0 :(得分:7)

这有效,但有点反模式。如果调用方法的线程不是主线程,我会做的是抛出错误。调用者有责任确保在正确的线程上调用方法,这些类型的黑客只会鼓励丑陋的代码。此外,如果您依赖于此,突然您每次调用此方法时都会将消息调度开销加倍。

如果您真的无法更改来电者的行为,可以尝试以下方法:

-(void)methodToBeRunOnMainThreadWithObj:(id)object {
    dispatch_sync(dispatch_get_main_queue(), ^{
        // code goes here
    });
}

这将导致调度块内的所有代码在主线程上执行,并且该方法在完成之前不会返回。如果您希望该方法立即返回,则可以使用dispatch_async代替。如果使用dispatch_sync,即使对于具有非void返回类型的方法,也可以使用此技巧。

此代码还具有支持具有非对象类型(int等)的参数的方法的额外好处。它还支持具有任意数量参数的方法,而performSelector:withObject:及其兄弟方法仅支持有限数量的参数。另一种方法是设置NSInvocation个对象,这些都很痛苦。

请注意,这需要您平台上的Grand Central Dispatch(GCD)。

答案 1 :(得分:3)

只要_cmd指定的选择器与文档中指定的定义/签名匹配,

_cmd转发即可。“该方法不应具有重要的返回值,应该采取一个类型为id的参数,或者没有参数。“。如果它不匹配,那么您应该假设未定义的行为。要保持110%安全并遵守抽象机器,返回类型应为id(或某些objc类型),结果不应返回拥有引用。