两个局部变量块可以互相调用吗?声明顺序引起的范围问题
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();
我有两个块声明为局部变量。出错时调用重试块的网络块,以及调用网络块的重试块。
重试块在几种不同的错误情况下被调用,因此使用块来消除重复代码。
但是,由于声明块的源代码顺序,这种情况不适用。
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();