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

Sea*_*ser 7 cocoa objective-c foundation nsthread ios

我遇到了这个_cmd伎俩:

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

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

yfr*_*cis 7

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

如果您真的无法更改调用方的行为,可以尝试以下操作:

-(void)methodToBeRunOnMainThreadWithObj:(id)object {
    dispatch_sync(dispatch_get_main_queue(), ^{
        // code goes here
    });
}
Run Code Online (Sandbox Code Playgroud)

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

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

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