iOS的weakSelf与strongSelf
2017-05-17 本文已影响522人
踏云小子
避免循环引用的标准做法:weakSelf+strongSelf
假设我们的类有一个属性叫做 model, 我们想要当 model 中的 data 变化的时候,有一个 label 的 text 会随之改变,为了达到这目的,我们设置 model :
- (void)setUpModel{
XYModel *model = [XYModel new];
model.dataChanged = ^(NSString *title) {
self.titleLabel.text = title;
};
self.model = model;
}
- (void)viewDidLoad {
[super viewDidLoad];
printf("retain count:%ld\n", CFGetRetainCount((__bridge CFTypeRef)(self)));
[self setUpModel];
printf("retain count:%ld\n", CFGetRetainCount((__bridge CFTypeRef)(self)));
}
果然,打印显示,引用计数+1了
image.png为啥?我们的 ViewController 持有了 model , model 持有了一个 Block , 这个 Block 又持有了 ViewController ,导致了循环引用。so通过添加 _weak 和 _strong 修饰的变量来打破循环引用,代码如下:
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) weakSelf = self;
model.dataChanged = ^(NSString *title) {
__strong typeof(self) strongSelf = weakSelf;
strongSelf.titleLabel.text = title;
};
self.model = model;
}
果然,效果很理想
image.png为什么要用strongSelf
其实大家可以试一下,直接用weakSelf,你会发现引用计数不变,那为啥要加这玩意儿,难道为了装逼?!主要是有时候weakSelf在block里在执行doSomething还存在,但在执行doMorething前,可能会被释放了,故为了保证self在block执行过程里一直存在,对他强引用strongSelf,一句话的事情
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) weakSelf = self;
model.dataChanged = ^(NSString *title) {
[weakSelf doSomething];
[weakSelf doMore];
};
self.model = model;
}
如果出现双层block嵌套甚至更多怎么办😰
看下面的例子,出现了两个block
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) weakSelf = self;
model.dataChanged = ^(NSString *title) {
__strong typeof(self) strongSelf = weakSelf;
strongSelf.titleLabel.text = title;
strongSelf.model.dataChanged = ^(NSString *title2) {
strongSelf.titleLabel.text = title2;
};
};
self.model = model;
}
结果引用计数+1了,shit,我们还需要对strongSelf再进行一次weakSelf-strongSelf
,如下
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) weakSelf = self;
model.dataChanged = ^(NSString *title) {
__strong typeof(self) strongSelf = weakSelf;
strongSelf.titleLabel.text = title;
__weak typeof(self) weakSelf2 = strongSelf;
strongSelf.model.dataChanged = ^(NSString *title2) {
__strong typeof(self) strongSelf2 = weakSelf2;
strongSelf2.titleLabel.text = title2;
};
};
self.model = model;
}
这样,就避免的引用循环,总结一下,不管都多少个block嵌套,皆按此法
更装逼的写法weakify + strongify
weakify 和 strongify其实是这样:
#define weakify(var) __weak typeof(var) XYWeak_##var = var;
#define strongify(var) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
__strong typeof(var) var = XYWeak_##var; \
_Pragma("clang diagnostic pop")
\\define加入反斜杠\表示换行意思
具体按下面使用:
- (void)setUpModel{
XYModel *model = [XYModel new];
weakify(self);
model.dataChanged = ^(NSString *title) {
strongify(self);
self.titleLabel.text = title;
};
self.model = model;
}
以上代码翻译下:
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) XYWeak_self = self;
model.dataChanged = ^(NSString *title) {
__strong typeof(self) self = XYWeak_self;
self.titleLabel.text = title;
};
self.model = model;
}