viewController被POP后不调用dealloc的问题
2017-12-02 14:08
363 查看
ARC下可以重写dealloc方法并在viewController被释放后自动调用,重写该方法时不能显式调用[super dealloc],因为系统会自动帮你调用父类的dealloc方法。
控制器在被pop后移出栈后会被释放,但有些时候会发现控制器出栈的时候不会调用dealloc方法,归根结底,是因为当前控制器被某个对象强引用了,控制器的引用计数不为0,系统无法帮你释放这部分内存。原因大致有以下几点:
控制器中NSTimer没有被销毁
当viewController中存在NSTimer时,需要特别注意,当调用
例如@property (nonatomic, weak) id delegate;代理要使用弱引用,因为自定义控件是加载在视图控制器中的,视图控制器view对自定义控件是强引用,如果代理属性设置为strong,则意味着delegate对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。
viewController中block的循环引用
在ARC下,block会把它里面的所有对象强引用,包括当前控制器self,因此有可能会出现循环引用的问题。比如viewController中有个block属性,在block中又强引用了self或者其他成员变量,那么这个viewController与自己的block属性就形成循环引用,导致viewController无法释放。
ddddd .png
由于循环引用的存在,造成在main()函数结束时,内存仍然无法释放,即内存泄露。编译器也会给出警告信息
Paste_Image.png再看一个例子:
作者:夜幕青雨
链接:http://www.jianshu.com/p/58f43fcbc197
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
控制器在被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; // 置nilviewController中的代理不是weak属性
例如@property (nonatomic, weak) id delegate;代理要使用弱引用,因为自定义控件是加载在视图控制器中的,视图控制器view对自定义控件是强引用,如果代理属性设置为strong,则意味着delegate对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。
viewController中block的循环引用
在ARC下,block会把它里面的所有对象强引用,包括当前控制器self,因此有可能会出现循环引用的问题。比如viewController中有个block属性,在block中又强引用了self或者其他成员变量,那么这个viewController与自己的block属性就形成循环引用,导致viewController无法释放。
// ARC enabled /************** MyObject Class **************/ typedefvoid(^myBlock)(void); @interfaceMyObject:NSObject { myBlock blk; } @end @implementationMyObject - (id)init { self=[superinit]; blk = ^{ NSLog(@"self = %@",self); }; returnself; } - (void)dealloc { NSLog(@"dealloc"); } @end /************** main function **************/ int main() { id myObject=[[MyObjectalloc] init]; NSLog(@"%@",myObject); return 0; }由于self是__strong修饰,在 ARC 下,当编译器自动将代码中的 block 从栈拷贝到堆时,block 会强引用和持有self,而self恰好也强引用和持有了 block,就造成了传说中的循环引用。
ddddd .png
由于循环引用的存在,造成在main()函数结束时,内存仍然无法释放,即内存泄露。编译器也会给出警告信息
warning: capturing 'self' strongly in this block is likely to lead to a retain cycle [-Warc-retain-cycles] blk = ^{NSLog(@"self = %@", self);}; note: Block will be retained by an object strongly retained by the captured object blk = ^{NSLog(@"self = %@", self);};为了避免这种情况发生,可以在变量声明时用__weak修饰符修饰变量self,让 block 不强引用self,从而破除循环。iOS4 和 Snow Leopard 由于对 weak 的支持不够完全,可以用__unsafe_unretained代替。
- (id)init { self = [super init]; id __weak tmp = self; blk = ^{NSLog(@"self = %@", tmp);}; return self; }
Paste_Image.png再看一个例子:
@interface MyObject : NSObject { myBlock blk; id _obj; } @end @implementation MyObject - (id)init { self = [super init]; blk = ^{ NSLog(@"_obj = %@", _obj); }; return self; } ... ... @end上面的例子中,虽然没有直接使用 self,却也存在循环引用的问题。因为对于编译器来说,_obj就相当于self->_obj,所以上面的代码就会变成
blk = ^{ NSLog(@"_obj = %@", self->_obj); };参考文章 [block没那么难(三):block和对象的内存管理]
作者:夜幕青雨
链接:http://www.jianshu.com/p/58f43fcbc197
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章推荐
- 工作问题小记 navigation push和popviewcontroller dealloc问题
- popViewControllerAnimated时未调用viewWillAppear问题
- navigation push和popviewcontroller dealloc问题
- 问题:viewController不会调用dealloc()不会销毁
- 在确认UIAlertView后,调用presentViewController无效的问题
- iOS8 自定义UITabBar (使用popToViewController导致的UITabBarButton重叠的问题)
- webview ZoomButtonsController 调用崩溃问题android.widget.ZoomButtonsController
- UINavigationController的popViewControllerAnimated问题
- popViewControllerAnimated 后的刷新问题
- popViewControllerAnimated的问题
- present viewcontroller 出来的h5调用相册问题
- IOS7 viewDidLoad中调用 pushViewController 的问题
- iOS8 自定义UITabBar (使用popToViewController导致的UITabBarButton重叠的问题)
- popViewControllerAnimated 无效的问题解决
- UINavigationController的popViewControllerAnimated问题
- UINavigationController的popViewControllerAnimated问题
- 使用dismissModalViewControllerAnimated 不调用dealloc 内存不释放解决方法
- UINavigationController的popViewControllerAnimated问题
- iOS viewcontroller中的dealloc方法不调用
- iOS 视图切换问题 popViewControllerAnimated 视图刷新问题