[__block / __weak 影响dealloc 释放]

参考

Block循环引用的三种解决方式
iOS开发——Block引起循环引用的解决方案
iOS 控制器POP后dealloc方法不走,通知监听无法移除的问题
assign weak copy block __block与__weak的区别

Bug背景

自定义一个导航控件,在处理左右按钮点击事件时,没有采用代理方法,而是使用Block

#pragma mark - 重写父类-导航设置方法
- (void)setNavCoverView{
    [super setNavCoverView];
    self.navCoverView.style = NavCoverStyleWhite;
    self.navCoverView.letfImgStr = @"login_icon_back";
    self.navCoverView.midTitleStr = @"测试";

    __block TestViewController *weakSelf = self;
    self.navCoverView.leftBlock = ^{
        [weakSelf.navigationController popViewControllerAnimated:YES];
    };

}

- (void)dealloc{
    NSLog(@"0-0-0-0-0");
}

以上代码中,由于使用了错误的 避免循环引用 方式 导致 dealloc() 方法不能被系统调用,这样是有问题的

经过测试 发现

  self.navCoverView.leftBlock = ^{
        //[weakSelf.navigationController popViewControllerAnimated:YES];

    };

- (void)dealloc{
    NSLog(@"0-0-0-0-0"); 
}

此时dealloc()方法被调用

问题出在 __block 上

__block:在ARC和MRC下都可用,可修饰对象,也可以修饰基本数据类型。

__block对象可以在block被重新赋值,__weak不可以。

__weak:只在ARC中使用,只能修饰对象,不能修饰基本数据类型(int、bool)。

同时,在ARC下,要避免block出现循环引用,经常会:__weak typedof(self) weakSelf = self;

    __weak typeof(self) weakSelf = self;
    self.navCoverView.leftBlock = ^{
        [weakSelf.navigationController popViewControllerAnimated:YES];
    };

使用 __weak 来避免循环引用 可避免导致 dealloc()方法不被调用

__weak typeof(self) weakSelf = self;

这句话的意思是声明了一个self类型的weak指针,名字叫做weakSelf. typeof是用来求参数类型的,这里也就是来求self的类型。这样定义出的weakSelf就是和self是一个类型,并且是原self的一个弱引用。

所以 也可以这样写

__weak MyViewController *weakSelf = self;  

补充:

对于block的修饰 copy/weak (转http://blog.sina.com.cn/s/blog_134b6ff380102v1y1.html)

使用总结:
1.当block里面会有b类相关的参数要回调回去的时候,属性用copy修饰,将其拷贝到堆里面,这样即便栈释放掉了,b类的指针也在堆中存在,能够成功的回调回去。
2.如果语法块仅仅是执行而不再回调回去了, 比如操作某个数据库,修改某个单利类的属性,发送某个通知之类的,则可以用weak来修饰。

有人会问:
为什么不能这里不都用copy呢,原因是 优化内存。 如果这个类要传入1000Block来执行,而这个类又不会马上释放掉的话,用copy是不是就拷贝了1000个在堆里面? 这样就会占用很大一部分内存,如果使用了weak将不必要的执行后就可以马上释放掉是不是就节约了很多的内存了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值