block应用与保留环

block应用与保留环
     block实际是oc的一种语法,EM demo中是习惯使用delegate方法完成异步回调,但由于block语法的使用的更加灵活与代码的可阅读性更好,因此lms部分的代码大量使用了block,但block的使用不好也容易引起较多问题,这里主要阐述循环引用与在viewControl中的code refactory上的优化作用。

循环引用的问题

iOS引用计数机制
     


     上图就是iOS中决定对象生命周期的引用计数(reference counting)的原理,即是只有对象被另外的对象强引用,那么该对象就不应该被释放,当然被释放了的对象也不能再向其发送消息,否则会发生野指针错误。

强引用与弱引用
     oc中的指针有两种类型,一种是强指针用__strong声明,另一种是弱指针用__weak声明。当然地,强指针对应强应用,而强应用的指针只要持有对象,对象就不会被释放。弱指针对应弱应用,弱应用就是所指的对象若被释放了,指针会置为nil,nil可以接收消息但不会响应,因此不会让程序奔溃。

引用block容易造成保留环
- ( void )viewDidLoad {
    [superviewDidLoad];
   dispatch_async(dispatch_get_global_queue(0,0), ^{
        NSString *str = self.NSString.
        NSLog(@“%@“,str);
    });
}
以上代码是定义在self类的对象中的,而block块中也调用了了self,因此self对象与block块的引用关系如下图。

在没有手动干预的情况下,两个对象的指针都是强指针,所以都无法释放,形成保留环,造成内存泄漏。而java还有垃圾回收机制,因此对这些保留环会定时情况,而oc只能靠开发人员多加注意了,但oc的内容重用的效率是比较高的,也因为没有垃圾回收机制,因此不会每隔一段时间需要消耗额外的资源去执行垃圾回收机制。关于block的保留环,就需要用过弱指针与强指针的搭配的解决。

强指针与弱指针搭配使用解决block模块引用的两个问题
 - ( void )viewDidLoad {
      [superviewDidLoad];
       __weak typeof ( self ) weakSelf = self ;                     //问题一:通过定义弱指针,解决保留环的问题
       dispatch_async ( dispatch_get_global_queue ( 0 , 0 ), ^{
           __strongtypeof(self) strongSelf = weakSelf;        //问题二:通过定义强指针,解决在block调用完之前,self被释放掉了,从而block的所有调用均无效
            NSLog ( @"%@" ,strongSelf. string );
      });
 }


     以上代码所描述的对象之间的指向关系如上图,从因为weakSelf是弱引用,所以并不持有self,weakSelf不影响self的生命周期,仅仅具备调用self的权限,而当self被释放后,又自动置为nil,从而确保不会发生野指针错误。
     至此,又容易引发另外的一个问题,当没有别的对象指向self后,self会执行dealloc method,进行释放。容易造成block还未执行完,便无法发送消息到self进行处理,甚至自身也被释放掉。
     因此需要在block中定义一个strongSelf指向weakS,从而指向self,因为block中的变量指向了self,那么self就不能在block没被释放的情况下释放了,保证了block中的内容能被正确执行。
     到这里,可能会有这样的疑问:为什么不直接用一个strongSelf解决所有的问题,反正最终都要强引用。假若把强引用变量strongSelf定义在block外面,因为block不持有对象,因此无法干预self的生命周期。若把强引用变量strongSelf定义在block内部,因为需要指向self,那么就会直接在block中引入self,造成保留环而发生内存泄漏。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值