Objective-C Blocks, Recursion Fails

前端 未结 3 1234
说谎
说谎 2020-12-28 23:03

Sup guys,

I\'m trying to do a function that calls itself but by putting everything on one block,

As you can see, the following function is intended to be cal

相关标签:
3条回答
  • 2020-12-28 23:42

    You have to declare your block itself as a block variable:

    __block void (^_test_closure)();
    
    
    _test_closure = ^{
        NSLog(@"Running...");
        if ((arc4random() % 100) > 50) {
            _test_closure();
        }
    }
    
    _test_closure();
    
    0 讨论(0)
  • 2020-12-28 23:48

    It works with XCode 5 - no warnings, no retain cycles:

    typedef void(^blockT)();
    
    blockT block1;
    blockT __block block1recursive;
    
    block1recursive = block1 = ^(){
        block1recursive();
    };
    
    block1();
    
    0 讨论(0)
  • 2020-12-28 23:55

    Recursion and blocks is tricky. Because a block captures all variables passed in, the variable _test_closure is not initialized yet (and clang should give you a warning:

    Block pointer variable '_test_closure' is uninitialized when captured by block

    ).

    There are several ways you can get around this, but the most obvious & simplest is to just make the block itself a __block variable (what @H2CO3 said). This allows the block to be weak-linked almost, so that when you call it again, it is properly initialized.

    Another option you have is making the block a global or static, like this:

    // outside of 'main', thus being a global variable
    void (^blockRecurse)(int) = ^(int level) {
        if (level < 0)
            return;
        NSLog(@"Level: %i", level);
        blockRecurse(--level);
    };
    
    int main()
    {
        @autoreleasepool {
            blockRecurse(10);
        }
    } 
    

    This means it's not being captured by the block, but instead it's referencing the global / static variable, which can be changed by all code equally.

    0 讨论(0)
提交回复
热议问题