关于block 中 何时使用 __weak/__block MyViewController * weakSelf 分析

来源:互联网 发布:雷蒙德钱德勒 知乎 编辑:程序博客网 时间:2024/06/05 18:08
说到block .想听我废话下它的基础。

block 是一个闭包函数。所谓闭包就是  

引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

oc 中 block 默认创建后 分配在栈中。。当向其 发送 copy 消息后 被移到堆上。 防止被释放。

由上面定义可以看出  block 会 保留在它所引用到的 一切变量。

 

__block 参数是什么? 修饰变量时 做了什么?

它是一个存储类型。 block 中体现为 不会保留 这样的变量。 同时 你可以在block 中修改(读写)它。

 

何时该用  __weak/__block  MyViewController * weakSelf ??

分析下面两个例子。

1,执行一个动画

[ UIView  animateWithDuration: 0.5  animations: ^ {
  self.someView . alpha  =  0 ;
}  completion: ^  ( BOOL  finished )  {
  [ self.someView  removeFromSuperView ];
}];

不用block 是这样的。
-  ( void ) fadeOutView  {

  [ UIView  beginAnimations ];
  [ UIView  setAnimationDuration: 0.5 ];
  [ UIView  setAnimationDelegate: self ];
  [ UIView  setAnimationDidStopSelector: @selector ( animationDidStop:finished:context: )];

  self.someView . alpha  =  0 ;

  [ UIView  commitAnimations ];
}

-  ( void ) animationDidStop: ( NSString  * ) animationID  finished: ( NSNumber  * ) finished  context: ( void  * ) context  {
  [self. someView  removeFromSuperView ];
}


2, 使用 一个 通知。

-  ( void ) setupNotifications  {
  [[ NSNotificationCenter  defaultCenter ]
      addObserverForNotificationName: MyWhizBangNotification
                              object: nil
                               queue: [ NSOperationQueue  mainQueue ]
                               block: ^ ( NSNotification  * notification )  {
                                 //reload该表以显示新的嗖bangs
                                 [ self . tableView  reloadData ];
                               }];
}

-  ( void ) dealloc  {
  [[ NSNotificationCenter  defaultCenter ]  removeObserver: self ];
  [ super  dealloc ];
}

不使用block 是这样的。

-  ( void ) setupNotifications  {
  [[ NSNotificationCenter  defaultCenter ]  addObserver: self
                                           selector: @selector ( onWhizBang: )
                                               name: MyWhizBangnotification
                                             object: nil ];
}

-  ( void ) onWhizBang: ( NSNotification  * ) notification  {
  //重新加载该表以显示新的嗖bangs
  [ self . tableView  reloadData ];
}

-  ( void ) dealloc  {
  [[ NSNotificationCenter  defaultCenter ]  removeObserver: self ];
  [ super  dealloc ];
}



对于前者是没有问题的, 后者是 有问题的。

来分析下 后者:
首先这里有 三个对象。
self .  NSNotificationCenter . block.

是的block 也是对象。

NSNotificationCenter 强引用着  self .

self 强引用着 block .

block 强引用着 self .

这里 NSNotificationCenter 和 self  关系没有问题。


当我们在self  的 dealloc 中

  [[ NSNotificationCenter  defaultCenter ]  removeObserver: self ];

将会  释放 block 对象。block 释放它引用的变量 self. 构成引用循环。

第一个例子为什么不会?

也是三个对象

self .  someView . block.

self 强引用view

block 强引用 view

而这里 block 是被 view的拥有者  self  强引用着。

这里并没有循环引用。 self 释放 时  block 会释放 view 。

 

所以对于这种情况 。解放办法是 在block 中不让它强引用 self 。如题使用

__block MyViewController *  weakSelf  和__weak  MyViewController *  weakSelf

可以达到一样效果。


参考文章:http://benscheirman.com/2012/01/careful-with-block-based-notification-handlers/

转载自:http://www.cnblogs.com/tangbinblog/p/4033365.html

0 0