iOS 内存斗争小史之 NavigationController
1、怎样写一个不泄漏的NavigationController页面跳转程序?
非arc模式下,假设有A、B两个viewController,从A推到B,怎样写内存才能不泄漏?
A.m
-(IBAction)btnGoToViewControllerB:(id)sender { ViewControllerB *aController = [[ViewControllerB alloc]init]; [self pushViewController:aController animated:YES]; [aController release]; //此处要释放 }
B.m
-(IBAction)btnGoToViewController1:(id)sender { [self.navigationController popViewControllerAnimated:YES]; //执行完本句后,系统会自动调用B类的dealloc方法,释放内存 }
我按照上面的步骤做的,为什么我的B类在pop时,系统没有调用dealloc方法呢?呵呵,如果真像上面说的那么简单,我就不写这片博客了。接着往下看!
首先,你的例子是新创建的工程吗,里面只有A B两个controller,而且除了必要的代码,没加其它的控件。如果是,你不会遇到这样的疑惑。是不是在网上down了一个工程来测试上面的代码,还是在自己的原开发工程里调试的。呵呵,不卖关了。
* 一个对象的dealloc方法若想被系统自动调用,前提是拴在此对象身上的狗链子已经全部消失,即retainCount为0.(在内存管理时,不建议去人工计算retainCount大小,来判断对象是否该释放了。应该使用对象“所有权”的思想去理解内存管理)。
* 我们知道alloc \ copy \ retain 操作会让你个对象被一个指针持有。但是,大家往往忽略对象本身self的赋值,也会被一个指针持有。如下:
self.tableView.delegate = self; //让self被tableView.delegate 持有,需要显示release
我们的viewControllerB没有如期被调用dealloc是因为这个对象还有指针持有它,还有狗链子拴着它呢!怎么释放?所以,要想对象被即使释放,请检查工程内,是否有哪个指针还持有这个对象。alloc \copy \ retain\和 *** = self;全部都要检查哦。
如果一个对象被一个指针,通过 *** = self;持有,那么应该在合适释放比较合适呢。dealloc肯定不行,因为只有对象没有持有者时系统才会进dealloc。一般地,应该写在返回按钮或其它页面跳转事件中。如下:
//返回 按钮 -(IBAction)btnBackClicked:(id)sender { [self.m_gridView.gridViewDelegate release]; //持有者 释放所有权 [self.navigationController popViewControllerAnimated:YES]; }
经验:
1、查看一个对象没有被及时释放,要重点检查其是否还有持有者。(用所有权地理念管理内存,而不是retainCount)
2、在实际编码中,dataSource也持有了对象如下:
aGridView.gridViewDelegate = self;
aGridView.gridViewDataSource = self;
但是却并不需要释放。如果释放了dataSource反而会引发过度释放的问题。具体原因,欢迎朋友告知。
参考:
解决循环引用问题: 一次IOS开发内存泄漏问题 iOS5中UIViewController的新方法
内存使用状态持续增长。。。(pop之前设置delegate为nil)
由pushViewController说起可能出线的各种死法