我遇到了这个_cmd
技巧:
-(void)methodToBeRunOnMainThreadWithObj:(id)object {
if (![NSThread isMainThread) {
[self performSelectorOnMainThread:_cmd withObject:object]
} else {
// ... method body
}
}
这是确保在主线程上执行方法的可靠方法吗?
答案 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类型),结果不应返回拥有引用。