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对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。
viewController中block的循环引用
在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正在载入页面,而不会马上被释放,等到页面载入完毕后,回调delegate(ViewController)中的方法,由于此时ViewController已经被释放,所以会出错。(message sent to deallocated instance)
解决办法是在dealloc中把WebView的delegate释放。
- (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