出于某种原因,我想在运行循环的下一次迭代期间执行一个块,所以我想出了:
typedef void (^resizer_t)() ;
- (void) applyResizer: (resizer_t) resizer {
resizer() ;
Block_release(resizer) ;
}
- (void) usage {
...
resizer_t resizer = ^() {
// stuff
} ;
[self performSelectorOnMainThread:@selector(applyResizer:)
withObject:(__bridge id) Block_copy((__bridge void *) resizer)
waitUntilDone:NO] ;
}
代码似乎有效,我没有发现泄漏也没有发现过早发布,但我对语法感到有些困惑......
答案 0 :(得分:13)
块被视为对象,因此ARC会阻止您在没有显式桥接转换的情况下将它们转换为void *
。奇怪的是你的编译器没有在Block_release
上抱怨:它应该(在我的机器上,它确实如此)。
由于ARC将块视为对象,因此您不再需要使用Block_copy
或Block_release
。当您希望它移动到堆并让编译器管理剩余部分时,复制块(带-[NSObject copy]
)。
-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]
保留接收者和参数对象,直到调用该方法。因此,您的块将在需要时保留并释放。您所要做的就是通过在将copy
消息传递给方法之前发送dispatch_async(dispatch_get_main_queue(), resizer);
消息来确保该块不存储在堆栈中。
此外,有一种更简单的方法来分配块的执行:它是libdispatch(又名GCD)。
{{1}}
答案 1 :(得分:4)
我希望在下一次运行循环迭代期间执行一个块
嗯,这就是你dispatch_after
的原因。如果你提供一个很小的时间值,它将具有你所追求的效果:你给出一个块,并且当当前的runloop完成并且重绘时刻已经发生时块将执行。
或者,如果您可以在不坚持阻止的情况下生活,请使用具有微小延迟值的performSelector:withObject:afterDelay:
(甚至为零)。这有同样的效果。
你所要求的是“延迟表现”并且很常见。所以这是常见的方式,框架给你的方式;不要试图像你的代码那样变得奇怪和幻想。