alm*_*now 7 closures block objective-c ios objective-c-blocks
苏家伙,
我正在尝试做一个自我调用的函数,但是将所有内容放在一个块上,
如您所见,以下函数旨在被无限次调用(直到arcrandom返回低于50的数字),并且您应该期望作为输出可变数量的"RUNNING"消息,具体取决于偶然性.
void (^_test_closure)(void) = ^ {
NSLog(@"RUNNING");
if(arc4random() % 100 > 50) {
_test_closure();
}
};
_test_closure();
Run Code Online (Sandbox Code Playgroud)
但是,在运行它时,我得到一个EXC_BAD_ACCESS错误,我发现的原因是,当代码试图在闭包内部调用_test_closure时,它基本上指向无处.
有谁知道如何使上述代码工作?
小智 8
您必须将块本身声明为块变量:
__block void (^_test_closure)();
_test_closure = ^{
NSLog(@"Running...");
if ((arc4random() % 100) > 50) {
_test_closure();
}
}
_test_closure();
Run Code Online (Sandbox Code Playgroud)
递归和块是棘手的.因为一个块捕获传入的所有变量,所以该变量_test_closure尚未初始化(并且clang应该给你一个警告:
当块捕获时,块指针变量'_test_closure'未初始化
).
有几种方法可以解决这个问题,但最明显和最简单的方法是将块本身变为__block变量(@ H2CO3所说的).这允许块weak-linked几乎,所以当你再次调用它时,它被正确初始化.
你有另一个选择是使块成为全局或静态,如下所示:
// 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着它不会被块捕获,而是引用全局/静态变量,可以由所有代码同等地更改.
| 归档时间: |
|
| 查看次数: |
4096 次 |
| 最近记录: |