self
只是块内捕获的变量,不引用块本身,那么块如何引用自身而没有明确的捕获变量来实现呢?
self
只是块内捕获的变量,不引用块本身,那么块如何引用自身而没有明确的捕获变量来实现呢?
__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
strawberryFields);
你使用 __block
是因为在创建块之前就会复制 strawberryFields
的值,这将发生在赋值之前。
在任何其他复制操作之前,你还必须 copy
块,否则你会得到一个引用了栈上原始版本的块。
请注意,上述代码会 泄露该块。 需要在某个地方释放那个块以平衡复制。
-(void) someMethod
{
// declare a __block variable to use inside the block itself for its recursive phase.
void __block (^myBlock_recurse)();
// define the block
void (^myBlock)() = ^{
// ... do stuff ...
myBlock_recurse(); // looks like calling another block, but not really.
};
// kickstart the block
myBlock_recurse = myBlock; // initialize the alias
myBlock(); // starts the block
}
一开始我尝试只是在myBlock
上加上__block
修饰符,并直接使用该变量在块的实现中进行递归。这在ARC Debug版本上可以工作,但在Release版本上会出现EXC_BAD_ACCESS
错误。另一方面,去掉__block
修饰符会引发“通过块捕获时未定义的变量”警告(我不愿意运行并测试它)。
myBlock
时会崩溃,但是当你使用 myBlock_recurse
时不会崩溃。 - user102008myBlock_recurse
赋值为nil
。 - adib我以前从未尝试过这个,也不确定它是否有用,但是举个例子:
typedef void (^BasicBlock)(void);
__block BasicBlock testBlock;
testBlock = ^{NSLog(@"Testing %p", &testBlock);};
testBlock();
你可能需要使用 __block 来声明变量,以防止出现 self-retain 循环。
__block
变量的地址通常会让人感到惊讶(因为有一个隐含的间接引用)。 - bbum__block
变量实际上是一个句柄,指向数据实际存储的位置。它最初位于堆栈上。当你执行Block_copy()(或-copy)时,它会在堆上分配一小块内存来保存变量的值,复制它,然后更新__block中的指针,使其不再指向堆栈。 - bbum这个块需要一些方法来清空它自己的引用。通常是通过将块存储在类的属性中来完成的。
有时您可能不想使用属性。以下是如何在没有属性的情况下完成它:
__weak id weakSelf = self;
__block id block = ^{
if(weakSelf) {
// .. do whatever
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
else {
block = nil;
}
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
__block
对象指针变量在ARC中是被保留的,而在MRC中则不是。因此,这将导致一个保留循环。为了避免保留循环,块需要捕获对自身的弱引用(使用__weak
)。__block __weak void(^weakBlock)();
void(^myBlock)();
weakBlock = myBlock = [^{ weakBlock(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
myBlock);
copy
,会发生什么? - trssweakBlock
将指向堆栈块。即使我们稍后使用块的副本(堆块),代码仍然引用指向堆栈块的weakBlock
,因此它将执行堆栈块并导致问题。这就是为什么在分配给weakBlock
之前必须复制该块的原因。 - newacctmyBlock
。赋值表达式会计算右侧的结果,并将该结果分配给一个强引用。编译器在赋值的顺序上有错误的挑剔。根据标准,代码是正确的,但我已经改变了它以消除警告。 - newacct
dispatch_async
之后立即释放呢? - user102008