1、Block生命周期:
int (^square) (int) = ^(int a ) {return a*a ;};
int result = square(5);
block一开始都是被放到stack,其生命周期随着method或function结束就会被回收,和一般变量的生命周期一样。
对于局部变量,block会把它copy下来,放在stack中。所以在后面的过程中修改局部变量的值,不会影响block的执行结果。如果block中使用的变量是 static 或者 指针 或者 __block ,修改才会影响结果。
[inBlock copy]的值就會被放到heap,就可以一直使用。但是-copy指令是为了要把block 从stack搬到heap,与原变量是有区别的。
2、解决循环引用:
最简单的方法就是使用带参数的block,参数会被复制到block的作用域。
如果想要修改变量的值,在变量申明前加 __block 使其被锁定,不再是局部变量
NSString *make = @"Honda"; NSString *(^getFullCarName)(NSString *) = ^(NSString *model) { return [make stringByAppendingFormat:@" %@", model]; }; NSLog(@"%@", getFullCarName(@"Accord")); // Honda Accord
多个参数的形式
NSString *(^getFullCarName)(NSString *,NSString *)= ^(NSString *model,NSString *mod) { ...... };
如果是系统提供的方法,无法修改block形式的:
__weak __typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if(strongSelf != nil) { [strongSelf doSomething]; [strongSelf doOtherThing]; } });
首先,在 block 之前定义对 self 的一个弱引用 weakSelf,因为是弱引用,所以引用指数不会加1,但是当 self 被释放时 weakSelf 会变为 nil;在 block 中引用该弱应用,通过使用强引用 strongSelf 来引用该弱引用,这时如果 self 不为 nil 就会 retain self,这样可以防止在后面的使用过程中 self 被其他地方释放;然后在之后的 block 块中使用该强引用 strongSelf,注意在使用前要对 strongSelf 进行了 nil 检测,因为多线程环境下在用弱引用 weakSelf 对强引用 strongSelf 赋值时,弱引用 weakSelf 可能已经为 nil 了。如果self是nil的话,一些情况下会crash。
__strong 确保在 Block 内strongSelf 不会被释放。
3、总结:
block会把变量copy到stack中,所以对变量的修改不会影响到heap上的数据。
如果要修改生效加__block,把变量锁定到heap上。
注意block里面的循环引用,主要就是self需要weak。
facebook的pop中是通过把self当做参数传递进去的。