Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The following recursive block code will compile and run using ARC, GC, or manual memory management, without crashing, leaking, or issuing warnings (analyzer or regular):</p> <pre><code>typedef void (^CountdownBlock)(int currentValue); - (CountdownBlock) makeRecursiveBlock { CountdownBlock aBlock; __block __unsafe_unretained CountdownBlock aBlock_recursive; aBlock_recursive = aBlock = [^(int currentValue) { if(currentValue &gt;= 0) { NSLog(@"Current value = %d", currentValue); aBlock_recursive(currentValue-1); } } copy]; #if !__has_feature(objc_arc) [aBlock autorelease]; #endif return aBlock; } - (void) callRecursiveBlock { CountdownBlock aBlock = [self makeRecursiveBlock]; // You don't need to dispatch; I'm doing this to demonstrate // calling from beyond the current autorelease pool. dispatch_async(dispatch_get_main_queue(), ^ { aBlock(10); }); } </code></pre> <p>Important considerations:</p> <ul> <li>You must copy the block onto the heap manually or else it will try to access a nonexistent stack when you call it from another context (ARC usually does this for you, but not in all cases. Better to play it safe).</li> <li>You need TWO references: One to hold the strong reference to the block, and one to hold a weak reference for the recursive block to call (technically, this is only needed for ARC).</li> <li>You must use the __block qualifier so that the block doesn't capture the as-yet unassigned value of the block reference.</li> <li>If you're doing manual memory management, you'll need to autorelease the copied block yourself.</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload