[英]Macro to run method on main thread
我想要一种简单的方法来在一个方法的开头删除代码,该方法将强制该方法仅在主线程上运行(因为该方法更新了UI元素)。
目前,我有类似的东西:
if (![NSThread isMainThread]){
[self performSelectorOnMainThread:_cmd withObject:_results waitUntilDone:NO];
return;
}
但是我想要一种方法将它包含在一个宏中而不必输入方法的参数。 看起来应该有一些方法来迭代传递给当前方法的参数列表并创建一个NSInvocation或类似的。 有什么想法吗?
这会有用吗?
#define dispatch_main($block) (dispatch_get_current_queue() == dispatch_get_main_queue() ? $block() : dispatch_sync(dispatch_get_main_queue(), $block))
如果你从主线程中调用它也会有效,这是一个奖励。 如果需要异步调用,只需使用dispatch_async
而不是dispatch_sync
。
我建议使用dispatch_sync()
和dispatch_get_main_queue()
来确保只有敏感代码在主线程上,而不是尝试在不同的线程上重新调用您的方法。 这可以很容易地包含在一个函数中,就像Brad Larson对“GCD在主线程中执行任务”的回答一样 。
他的程序与你已经拥有的程序基本相同,不同之处在于代码被放入一个块中,并根据需要调用或排队:
if ([NSThread isMainThread])
{
blockContainingUICode();
}
else
{
dispatch_sync(dispatch_get_main_queue(), blockContainingUICode);
}
如果您愿意,也可以毫不费力地将其翻译成宏。
创建块本身并不需要进行太多更改。 如果您的UI代码如下所示:
[[self textLabel] setText:name];
[[self detailTextLabel] setText:formattedDollarValue];
[[self imageView] setImage:thumbnail];
将它放入要排队的区块中就像这样:
dispatch_block_t blockContainingUICode = ^{
[[self textLabel] setText:mainText];
[[self detailTextLabel] setText:detailText];
[[self imageView] setImage:thumbnail];
};
我知道从这样的方法创建动态NSInvocation的唯一方法是需要将方法的参数作为va_list。
您需要能够将当前方法的参数作为数组(以便您可以循环数组并将参数添加到NSInvocation)并且我不确定这是否可行(我不认为这是可能的) )。
如果使用NSThread条件三元从主线程或后台线程调用,这将起作用。
同步:
#define dispatch_main(__block) ([NSThread isMainThread] ? __block() : dispatch_sync(dispatch_get_main_queue(), __block))
异步:
#define dispatch_main(__block) ([NSThread isMainThread] ? __block() : dispatch_async(dispatch_get_main_queue(), __block))
使用:
-(void)method {
dispatch_main(^{
//contents of method here.
});
}
归因:灵感来自理查德罗斯的答案
我认为这就是你要找的东西:
- (void)someMethod
{
// Make sure the code will run on main thread
if (! [NSThread isMainThread])
{
[self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:YES];
return;
}
// Do some work on the main thread
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.