(0055)iOS开发之dealloc认识

dealloc:

ARC唯一一个留着 dealloc 方法的原因就是, 你需要释放一些不在 ARC 控制下的资源。 例如 Core Foundation 对象中调用 CFRelease() 对那些通过 malloc() 分配的内存调用 free(), 注销通知,停止 Tiner 等等。


iOS中viewController被POP后不调用dealloc的问题?


ARC下可以重写dealloc方法并在viewController被释放后自动调用,控制器在被pop后移出栈后会被释放,但有些时候会发现控制器出栈的时候不会调用dealloc方法,归根结底,是因为当前控制器被某个对象强引用了,控制器的引用计数不为0,系统无法帮你释放这部分内存。原因大致有以下几点:


控制器中NSTimer没有被销毁

viewController中存在NSTimer时,需要特别注意,当调用[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:userInfo:nil repeats:YES]

时,因为 target:self ,也就是引用了当前viewController,导致控制器的引用计数加1,如果没有将这个NSTimer 销毁,它将一直保留该viewController,无法释放,也就不会调用dealloc方法。所以,需要在viewWillDisappear之前需要把控制器用到的NSTimer销毁。

[timer invalidate]; // 销毁timer

timer = nil; // nil


viewController中的代理不是weak属性

例如@property (nonatomic, weak) id delegate;代理要使用弱引用,如果代理属性设置为strong,则意味着delegate对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。


viewControllerblock的循环引用

ARC下,block会把它里面的所有对象强引用,包括当前控制器self,因此有可能会出现循环引用的问题。比如viewController中有个block属性,在block中又强引用了self或者其他成员变量,那么这个viewController与自己的block属性就形成循环引用,导致viewController无法释放。

由于self__strong修饰,在 ARC 下,当编译器自动将代码中的 block 从栈拷贝到堆时,block 会强引用和持有self,而self恰好也强引用和持有了 block,就造成了传说中的循环引用。


为了避免这种情况发生,可以在变量声明时用weak修饰符修饰变量self,让 block 不强引用self,从而破除循环。


dealloc该写些什么?

在非ARC开发环境中,dealloc是类释放前,清理内存的最后机会。到底那些变量和属性该释放呢,一些特殊的类(nstimer,observer)该怎么释放?


- (void)dealloc

{

    // 1. 通知的释放

    [[NSNotificationCenter defaultCenter]removeObserver:self]; 


    // 2. delegate的释放 

    // delegate属性的赋值一般为self,虽然声明时assign,但在相关的view释放时,在之前先释放掉delegate

    // 情况一

      if (_loadingContentView) {

        _loadingContentView.delegate = nil;

        [_loadingContentView removeFromSuperview];

      }

     // 情况二 

     self.partGridView.uiGridViewDelegate = nil;

     self.partGridView = nil;


     // 3. 变量的释放

     [brandview release];

     // 4. 属性的释放

      self.labelTitle = nil; 


     // 5.定时器释放

     // 如果实在view中声明初始化的,要在 controller中view释放前先释放定时器,否则由于循环引用,而释放不掉

      if (landscape) {

           [landscape->timer invalidate];

       }

      SafeRelease(landscape);

}


iOS ARC环境下dealloc的使用

一般使用ARC的话,dealloc函数是不需要实现的,写了反而会出错。但有些特殊的情况,dealloc函数还是需要的。比如,在画面关闭的时候,需要把ViewController的某些资源释放,在viewDidDissppear不一定合适,这时dealloc里实现:


举个例子,画面上有UIWebView,它的delegate是该画面的ViewController,在WebView载入完成后,需要做某些事情,比如,把indicator停掉之类的。如果在WebView载入完成之前关闭画面的话,画面关闭后,ViewController也释放了。但由于WebView正在载入页面,而不会马上被释放,等到页面载入完毕后,回调delegateViewController)中的方法,由于此时ViewController已经被释放,所以会出错。(message sent to deallocated instance

解决办法是在dealloc中把WebViewdelegate释放。

- (void)dealloc {

    self.webView.delegate = nil;

}


ARC下,系统可以帮我们释放该对象,及其包含的对象;但是却无法释放不属于该对象的一些东西,如:由于通知中心是系统的一个单例,你在注册通知的观察者时,实际上是在通知中心注册的,这时,即使ARC下系统帮我们释放了对象,但是在通知中心的观察还是没有移除,那么当有该通知时,依然会尝试调用该对象的接受通知的方法,这可能会导致一些问题.

另外, 在你的 dealloc 方法中, 你仍然可以使用实例变量, 因为他们在这时候还没被释放掉。 dealloc 返回之前,都不会被释放。  



参考:http://blog.csdn.net/xdrt81y/article/details/10107409

:http://blog.csdn.net/musou_ldns/article/details/7673795


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值