block-循环引用

在ARC机制下,app的内存管理由操作系统进行管理,不需要程序员手动的管理内存,方便了开发.尽管,自动释放内存很方便,但是并非绝对安全,绝对不会产生内存泄露。大部分导致iOS对象无法按预期释放的一个无形杀手是——循环引用。循环引用可以简单理解为A引用了B,而B又引用了A,双方都同时保持对方的一个强引用,导致任何时候引用计数都不为0,始终无法释放。

下面我们介绍下block代码块,引起的循环引用以及解决办法

block在copy时都会对block内部用到的对象进行强引用。第一种容易引起循环引用的一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.MyBlock = ^(Type var){[self dosomething]; 或者self.otherVar = XXX;或者_otherVar = …}, 造成了self 拥有一个block的时候,在block 又调用self的方法。block的这种循环引用会被编译器捕捉到并及时提醒。
举例如下(People类):
事例1
我们可以看出在block的实现内部又使用了People类(self)的name属性,这个时候,编译器提醒给出了相关的警告.
解决方法:
解决方法
通过使用_weak声明一个代替self的新变量代替原先的self,命名为weakSelf。通过这种方式告诉block,不要在block内部对self进行强制强引用.
这种循环引用的事例图为:
事例图

第二种情况为:例如self 有一个button ,而你有要 调用 button的某个东西设置.[self.button ^{ }]由于某些原因,你又要在这个block里调用self的其他控件,例如self.textField.text = @”text”;就造成了讯混引用。(即:控制器中有一个控件,在这个控件中又访问了控制器的其他控件).例如AlertController中的Action对象访问AlertController的textField对象.
为了进行演示的事例:首先我们定义了一个UIAlertController的子类(AlertController),并实现它的dealloc方法

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

监控是否销毁
在主控制器中创建AlertController,并实现点击确认的方法(获取其上的文本框内容信息)

点击确认后,打印如下
结果
我们发现在销毁AlertController的时候,AlertController并没有释放,导致了内存的泄露.

修改为如下方式,点击确认后结果为:
更改方法
可以看出,对象得到释放.
没有修改之前的事例图为:
strong
解决循环引用后
解决

解决方法
简而言之就一句话的事情:

__weak typeof (self) weakSelf = self;
posted @ 2016-04-04 15:43  zsper  阅读(185)  评论(0编辑  收藏  举报