Is there a SELF pointer for blocks?

前端 未结 4 1556
粉色の甜心
粉色の甜心 2020-12-25 14:09

I\'d like to recursively call a block from within itself. In an obj-c object, we get to use \"self\", is there something like this to refer to a block instance from inside i

4条回答
  •  被撕碎了的回忆
    2020-12-25 15:07

    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):

    typedef void (^CountdownBlock)(int currentValue);
    
    - (CountdownBlock) makeRecursiveBlock
    {
        CountdownBlock aBlock;
        __block __unsafe_unretained CountdownBlock aBlock_recursive;
        aBlock_recursive = aBlock = [^(int currentValue)
        {
            if(currentValue >= 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);
                       });
    }
    

    Important considerations:

    • 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).
    • 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).
    • You must use the __block qualifier so that the block doesn't capture the as-yet unassigned value of the block reference.
    • If you're doing manual memory management, you'll need to autorelease the copied block yourself.

提交回复
热议问题