http://www.jianshu.com/p/f4fa7aeb2035
一般说的block无法改变局部变量,必须加__block才可以
准确的说是无法改变局部变量的地址,如果该局部变量是一个Student类的对象,你无法再block中将其=nil,但是可以修改.name属性.因为=nil时其实是改变了他的内存地址,而修改.name不会改变内存地址
__weak typeof(self) mv=self;正常是这样
=================================
MASonry中使用self不需要弱引用 网络封装中也不需要弱引用
MJRefresh中必需要弱引用)
ATTNetWork中successBlock和faildBlock出现Self不需要弱引用.. 正确是ATTNetWork强引用Self,所以当在VC中请求还没完成,然后pop退出当前VC,会造成VC先不释放,等到Success或者faild的时候,执行完successBlock或者faildBlock之后VC才会销毁 如果
=================================
如果在myBlock中嵌套my2Block
self.testView.myBlock = ^{
NSLog(@"shuchu1");
test2View.my2Block = ^{
self;
NSLog(@"shuchu2");
};
};
那么self.testView会强引用test2View,也会强引用self,test2View会强引用self
==============================
解决 retain circle
Apple 官方的建议是,传进 Block 之前,把 ‘self’ 转换成 weak automatic 的变量,这样在 Block 中就不会出现对 self 的强引用。如果在 Block 执行完成之前,self 被释放了,weakSelf 也会变为 nil。
示例代码:
1 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 [weakSelf doSomething];
4 });
clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外:
1 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 [weakSelf doSomething];
4 [weakSelf doOtherThing];
5 });
在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,于是,strongSelf 就派上用场了:
1 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 __strong __typeof(self) strongSelf = weakSelf;
4 [strongSelf doSomething];
5 [strongSelf doOtherThing];
6 });
__strong 确保在 Block 内,strongSelf 不会被释放。
总结
在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。
如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。
-------------------------------分割线---------------------------------------------
以上内容知道了我们为什么要用weakSelf和strongSelf, 为了简单实用一般会定义成宏weakify和strongify,如下:
View Code
使用过RAC的同学应该都知道@weakify和@strongify,这两个宏在RAC中是已经定义好的,可以直接用,属于比较牛逼的写法。这两个宏一定成对出现,先@weakify再@strongify.可以很好的管理Block内部对self的引用。可以一步步点开发现其实使用到了C语言中的组合运算符。
1 @weakify(self);
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 @strongify(self);
4 [self doSomething];
5 [self doOtherThing];
6 });
block中如果用了下划线_的形式,其实用@weakify(self) 和@strongify(self)其实还是不行的
=====================================
看下面的例子:block中套block要这样写才不会循环引用
@weakify(self);
[[ATTNetwork shareInstance]getWithURL:GetHotListURL token:nil params:params success:^(id response) {
@strongify(self);
} failure:^(NSError *error) {
@strongify(self);
@weakify(self);
[self.backView showNoNetWorkWithTryAgainBlock:^{
@strongify(self);
[self loadDataFromCache:NO];
}];
}
}];
网友评论