ARC __bridge强制转换Block_copy和Block_release

出于某种原因,我想在运行循环的下一次迭代期间执行一个块,所以我想出了:

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] ; } 
  1. 具体而言,我必须强制转换为Block _copy的论点吗?
  2. 为什么编译器对我的Block_release感到满意,因为它在没有桥接器void * cast的情况下阻塞Block_copy?

代码似乎工作,我没有检测到泄漏也没有过早发布,但我对语法有点困惑……

块被视为对象,因此ARC会阻止您在没有显式桥接转换的情况下将它们转换为void * 。 奇怪的是你的编译器没有抱怨Block_release :它应该(在我的机器上,它确实)。

因为ARC将块视为对象,所以不再需要使用Block_copyBlock_release 。 当您希望它移动到堆并让编译器管理剩余部分时,复制该块(使用-[NSObject copy] )。

-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]保留接收者和参数对象,直到调用该方法。 因此,您的块将在需要时保留并释放。 您所要做的就是通过在copy消息传递给方法之前发送copy消息来确保该块不存储在堆栈中。

此外,有一种更简单的方法来分配块的执行:它是libdispatch(又名GCD)。

 dispatch_async(dispatch_get_main_queue(), resizer); 

我希望在运行循环的下一次迭代期间执行一个块

好吧,这就是你有dispatch_after的原因。 如果你提供一个很小的时间值,它将具有你正在经历的效果:你给出一个块,并且当当前的runloop完成并且重绘时刻已经发生时块将执行。

或者,如果您可以在不坚持块的情况下生存,请使用performSelector:withObject:afterDelay:具有微小的延迟值(甚至为零)。 这具有相同的效果。

你所要求的是“延迟表现”并且很常见。 所以这是常见的方式,框架给你的方式; 不要试图像你的代码那样变得奇怪和幻想。