两个局部变量块可以互相调用吗?声明顺序引起的范围问题

Can two local variable blocks call each other? Scope issue due to order of declaration

我有两个块声明为局部变量。出错时调用重试块的网络块,以及调用网络块的重试块。

重试块在几种不同的错误情况下被调用,因此使用块来消除重复代码。

但是,由于声明块的源代码顺序,这种情况不适用。

void (^upperBlock)() = ^{

    // variable is used before it is declared.
    lowerBlock(); // Error: implicit declaration of function `lowerBlock` is invalid in C99
};

void (^lowerBlock)() = ^{
    upperBlock(); // ok!
};

给低层块一个前向声明是行不通的,因为上层块在变量重新赋值之前捕获了前向声明的初始值(即使它被调用 稍后)。

void (^lowerBlock)() = nil;

void (^upperBlock)() = ^{
    lowerBlock(); // crash! block is `nil`
};

lowerBlock = ^{
    // new value not assigned, despite `upperBlock` being *called* below this point
};

upperBlock()

我可以在 lowerBlock 上使用 __block,在这种情况下,upperBlock 将调用新分配的变量版本。但是,如果可以使用另一种解决方案,那么使用 __block 似乎对这种情况有点矫枉过正。

是否有任何内联的、块作为局部变量的解决方案来允许上下块相互引用?

除非变量被标记为 __block,否则捕获是按块的值进行的。这是正确的解决方案。

如果您将 lower 声明为 __block 变量,它将被捕获为引用而不是副本,并且 upper 将看到它的 "current" 调用时的值:

__block BOOL proceedWithInfiniteRegress = YES;
__block dispatch_block_t lower;

dispatch_block_t upper = ^{
    if( proceedWithInfiniteRegress ){
        lower();
    }
};

lower = ^{
    proceedWithInfiniteRegress = NO;
    NSLog(@"Hello, reference cycle!");
    upper();
};

upper();