在ios常见的循环引用中曾经提到过block:
看看上面最基本的block循环应用,self包含block,block包含了self中的变量val,所以形成了循环应用,编译器给出了循环引用的警告,当然不是所有的block循环引用编译器都能给出警告,所以不要只依赖编译器的警告来判断循环引用,如:
解决的办法当然是使用__weak来修饰self
__weak typeof(self) weakSelf = self;
blkk = ^{
[weakSelf showLog];
};
blkk();
-------------------------------凌乱分割线-------------------------------
正常在栈上的block引用self是不会引起循环应用的,所以可以不使用weak来修饰self
void (^blkk)(void) = ^{
[self showLog];
};
blkk();
但是因为block的使用附有__strong的原因,虽然不会有循环引用,但是也会起到延长self对象的生命周期的效果,直到栈上的block释放了,才会释放self。
因此释放self可能会让程序出现问题,假如self监听了某些通知而修改公共资源什么的,所以这种情况下最好也使用weakself。
当然你也可能不希望self提前释放,因为你的block回调后需要进行完整操作,假如self释放了,你无法在block回调后来处理一些其他的事情,这时候你可以选择不使用weakself,也可以使用weakself+strongself。先看看weakself+strongself的写法:
__weak __typeof__(self) weakSelf = self;
createdTask = [self.sessionManager
dataTaskWithRequest:request
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
dispatch_async(self.responseQueue, ^{
__strong __typeof__(weakSelf) strongSelf = weakSelf;
.....
上面是AFNetworking的源码,在block前用了weakself,在block里用了strongself,这样做和直接不使用weakself有什么区别呢。
block回调前结束self
block回调后结束self
不使用weakself
self 不释放
self不释放
weakself+strongself
self已释放
self不释放
使用weakself
self已释放
self已释放
所以根据情况的不同,大家可以选择使用哪种方式。当然最无脑的推荐还是使用weakself