1.由上篇文章,已经了解到,weak是可以避免循环引用的,那么__weak的作用是什么呢,答案是:也是避免循环引用的,只不过__weak一般是在使用block的时候,用来避免循环引用的。但是要注意的是,由于__weak,不持有该对象,如果在该对象已经释放了之后,再访问block的话,在block内部就无法再访问到该对象了,为了避免该情况的发生。可以在block内部,再声明一个__strong变量来指向weakObj,使外部对象既能在 block 内部保持住,又能避免循环引用的问题。
使用时,代码如下:
MyObject *obj = [[MyObject alloc] init];
__weak MyObject *weakObj = obj;
obj.block = ^{
__strong MyObject *strongObj = weakObj;
};
那么__block可以避免循环引用么,答案是不可以的。因为__block会持有该对象,即使超出了该对象的作用域,该对象还是会存在的,直到block对象从堆上销毁;而__weak仅仅是将该对象赋值给weak对象,当该对象销毁时,weak对象将指向nil。
2.那么__block有什么作用呢?
(1)我们知道,在使用block中,block内部是可以访问外部的变量的,但是却不能修改外部变量。如下代码:
这时候Xcode会提示x变量错误信息:Variable is not assigning (missing __block type)。
若要修改这个外部变量,__block就派上用场了,我们需要给这个变量加上__block修饰符。
(2)没有__block修饰的时候,在调用block的时候,只是在创建block的时候,直接捕获了该变量的当前值(当前值,要注意哈),而再block之后,无论如何改变这个变量的值,block内部里的这个变量的值,始终保持捕获时的值,如下代码所示:
[super viewDidLoad];
int count = 10;
self.block = ^{
NSLog(@"%zi",count);
};
count = 5;
self.block();
}
输出结果为10,而不是5
block使用举例[56199:3675614] 10
而如果加了__block修饰符的话,__block实际是指向了变量的地址,后期该变量改变时,__block指向的变量的值也改变。
代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
__block int count = 10;
self.block = ^{
NSLog(@"%zi",count);
};
count = 5;
self.block();
}
输出结果为:
block使用举例[56432:3683108] 5
那为什么加上__block就可以指向变量的地址了呢,且看下篇文章,下篇文章,将深入研究block的内部原理。