首页 > 代码库 > 关于block 中 何时使用 __weak/__block MyViewController * weakSelf 分析

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

说到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/













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