ARC __bridge cast Block_copy & Block_release

For some reason, I want the block to execute during the next iteration of the execution loop, so I came up with:

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] ; } 
  • Isn’t it ironic that I should throw * Block_copy argument on the void *?
  • Why is the compiler happy with my Block_release when it throttles to Block_copy without a void * cast bridge?

It seems that the code is working, I did not find a leak or a premature release, but I am a bit puzzled by the syntax ...

+4
source share
2 answers

The block is processed as objects, so ARC forbids you to translate them to void * without an explicit bridge. It is strange that your compiler does not complain about Block_release : it should (on my machine, it does).

Since ARC treats the block as objects, you no longer need to use Block_copy and Block_release . Copy the block (using -[NSObject copy] ) when you want it to move to the heap and allow the compiler to control the remainder.

-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] saves the receiver and parameter object until the method is called. Thus, your block will be saved and released when required. All you have to do is make sure the block is not stored on the stack by sending a copy message before passing it to the method.

In addition, there is an easier way to send a block execution: libdispatch (aka GCD).

 dispatch_async(dispatch_get_main_queue(), resizer); 
+13
source

I want the block to execute during the next iteration of the run loop

Ok, that is why you have dispatch_after . If you specify a small value of time, it will have exactly the effect that you need: you give the block, and the block will be executed as soon as the current runloop is completed, and the moment of redrawing occurs.

Or, if you can live without insisting on a block, use performSelector:withObject:afterDelay: with a small delay value (even zero). This has the same effect.

What you are asking for is called deferred performance and is very common. So do it in the usual way, as the structure gives you; don't try to get everything weird and weird as your code does.

+4
source

Source: https://habr.com/ru/post/1401367/


All Articles