避免循環(huán)引用的標(biāo)準(zhǔn)做法:weakSelf+strongSelf
假設(shè)我們的類有一個(gè)屬性叫做 model, 我們想要當(dāng) model 中的 data 變化的時(shí)候掉缺,有一個(gè) label 的 text 會(huì)隨之改變态秧,為了達(dá)到這目的少办,我們?cè)O(shè)置 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)));
}
果然,打印顯示蟹演,引用計(jì)數(shù)+1了
為啥风钻?我們的 ViewController 持有了 model , model 持有了一個(gè) Block , 這個(gè) Block 又持有了 ViewController ,導(dǎo)致了循環(huán)引用酒请。so通過添加 _weak 和 _strong 修飾的變量來打破循環(huán)引用骡技,代碼如下:
- (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;
}
果然,效果很理想
為什么要用strongSelf
其實(shí)大家可以試一下羞反,直接用weakSelf布朦,你會(huì)發(fā)現(xiàn)引用計(jì)數(shù)不變,那為啥要加這玩意兒昼窗,難道為了裝逼是趴?!主要是有時(shí)候weakSelf在block里在執(zhí)行doSomething還存在澄惊,但在執(zhí)行doMorething前唆途,可能會(huì)被釋放了富雅,故為了保證self在block執(zhí)行過程里一直存在,對(duì)他強(qiáng)引用strongSelf肛搬,一句話的事情
- (void)setUpModel{
XYModel *model = [XYModel new];
__weak typeof(self) weakSelf = self;
model.dataChanged = ^(NSString *title) {
[weakSelf doSomething];
[weakSelf doMore];
};
self.model = model;
}
如果出現(xiàn)雙層block嵌套甚至更多怎么辦??
看下面的例子没佑,出現(xiàn)了兩個(gè)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;
}
結(jié)果引用計(jì)數(shù)+1了,shit温赔,我們還需要對(duì)strongSelf再進(jìn)行一次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;
}
這樣,就避免的引用循環(huán)让腹,總結(jié)一下远剩,不管都多少個(gè)block嵌套,皆按此法
更裝逼的寫法weakify + strongify
weakify 和 strongify其實(shí)是這樣:
#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;
}