ios block(4)

来源:未知 责任编辑:责任编辑 发表时间:2015-09-17 09:44 点击:

p>}  

p>  

p>  

p>- (void)dealloc  

p>{  

p>    if (_observer) {  

p>        [[NSNotificationCenter defaultCenter] removeObserver:_observer];  

p>    }  

p>}  

p> 

p> 

p> 

p> 

p>在上面代码中,我们添加向通知中心注册了一个观察者,然后在 dealloc 时解除该注册,一切看起来正常。但这里有两个问题:

p> 

p> 

p>a) 在消息通知 block 中引用到了 self,在这里 self 对象被 block retain,而 _observer 又 retain 该 block的一份拷贝,通知中心又持有 _observer。因此只要 _observer 对象还没有被解除注册,block 就会一直被通知中心持有,从而 self 就不会被释放,其 dealloc 就不会被调用。而我们却又期望在 dealloc 中通过 removeObserver 来解除注册以消除通知中心对 _observer/block 的 retain。

p> 

p> 

p>b) 同时,_observer 是在 self 所在类中定义赋值,因此是被 self retain 的,这样就形成了循环引用。

p> 

p> 

p>上面的过程 a) 值得深入分析一下:

p> 

p> 

p>苹果官方文档中对 addObserverForName:object:queue:usingBlock: 中的 block 变量说明如下:

p> 

p> 

p>The block is copied by the notification center and (the copy) held until the observer registration is removed.

p> 

p> 

p>因此,通知中心会拷贝 block 并持有该拷贝直到解除 _observer 的注册。在 ARC 中,在被拷贝的 block 中无论是直接引用 self 还是通过引用 self 的成员变量间接引用 self,该 block 都会 retain self。

p> 

p> 

p>这两个问题,可以用 weak–strong dance 技术来解决。该技术在 WWDC 中介绍过:2011 WWDC Session #322 (Objective-C Advancements in Depth)

p> 

p> 

p> 

p> 

p>[cpp]  

p>__weak KSViewController * wself = self;  

p>_observer = [[NSNotificationCenter defaultCenter]  

p>             addObserverForName:@"TestNotificationKey"  

p>             object:nil queue:nil usingBlock:^(NSNotification *n) {  

p>                 KSViewController * sself = wself;  

p>                 if (sself) {  

p>                     NSLog(@"%@", sself);  

p>                 }  

p>                 else {  

p>                     NSLog(@"<self> dealloc before we could run this code.");  

p>                 }  

p>             }];  

p> 

p> 

p> 

p> 

p>下面来分析为什么该手法能够起作用。

p> 

p> 

p>首先,在 block 之前定义对 self 的一个弱引用 wself,因为是弱引用,所以当 self 被释放时 wself 会变为 nil;然后在 block 中引用该弱应用,考虑到多线程情况,通过使用强引用 sself 来引用该弱引用,这时如果 self 不为 nil 就会 retain self,以防止在后面的使用过程中 self 被释放;然后在之后的 block 块中使用该强引用 sself,注意在使用前要对 sself 进行了 nil 检测,因为多线程环境下在用弱引用 wself 对强引用 sself 赋值时,弱引用 wself 可能已经为 nil 了。
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
用户名: 验证码:点击我更换图片
最新评论 更多>>

推荐热点

  • Lexical or Preprocessor Issue 'xxx.h
  • ios学习笔记(二)xcode 4.3.2下实现基本交互
  • ios学习笔记(一)xcode 4.3.2下创建第一个ios项目
  • UITableView一些方法
  • IOS类似iphone通讯录TableView的完整demo【附源码】
  • ios版本的helloworld
  • iPhone SDK开发:本地文本文件内容的读取
  • 如何为Iphone应用创建启动界面
  • 去掉屏幕键盘的方法
网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
Copyright © 2008-2015 计算机技术学习交流网. 版权所有

豫ICP备11007008号-1