在iOS中,循环引用是不可忽视的一个问题,因为循环引用极有可能会造成内存泄漏,是衡量一个app是否健康且高质量的标准之一。如何去解决循环引用呢,笔者在此提出三种解决方式:
1.使用__weak和__strong;
2.使用__block修饰变量,在block内部需要使用全部变量时暂用__block代替,在block外部再做有关全局变量的操作;
3.使用self作为block的参数,也可解决循环引用。
下面我们重点分析第一种情况,使用__weak和__strong解决循环引用:
在block内部如果需要使用实例方法或者实例变量,首先应定义: __weak typeof(self) weakSelf = self;
在block中可以再次定义strongSelf对weaSelf进行持有,如果可以确定block是同步执行的,那么可以不需要使用strong重新声明。接下来是我们的重点,为什么__weak可以解决循环引用:
1.__weak使用之后,会调用__objc_initWeak函数,storeWeak函数等,将要指向的对象地址(id *location)以及指针(objc_object *newObj)传入storeWeak函数,通过hash表映射,location作为key,newObj作为value,存储在weakTable中进行维护。weak指针指向对象,不会让对象的引用计数增加,所以block内部就不会持有self对象,破解循环引用;
2.为什么异步时需要使用strong再对对象重新声明?如果在异步执行的过程中,self被释放,会调用objc_clear_deallocating(id obj)方法,下一步调用clearDeallocating方法,紧接着调用
weak_clear_no_lock(weak_table_t *weak_table, id referent)
函数,在hash表中根据key(对象地址)寻找weak指针的数组,遍历置空。所以为了避免self被释放掉导致后续流程无法走通,使用strong强引用弱指针,执行过程中weak指针就不会被释放,在执行完成之后再释放置空。
3.为什么strong不会造成循环引用呢?因为strong实在block内部创建的,属于局部变量,强引用的也是weak指针,在block执行完成后,strongSelf变量就会被释放,这个临时的“循环引用”就会被打破。
如有不正确之处,请各位读者评论指正,谢谢。(QQ:1309595446)