iOS中viewDidUnload替代方案及视图切换时注销通知监听方法咨询
iOS 相关问题解答
一、viewDidUnload 的替代方案
viewDidUnload 在 iOS 6 就被官方废弃了,主要原因是 ARC 普及后系统内存管理机制更智能,不再需要依赖这个方法手动清理视图资源。目前常用的替代方案有这几种:
- 内存警告时针对性清理:在
didReceiveMemoryWarning方法中,判断当前控制器的视图是否处于显示状态,如果视图不在窗口上,就主动释放可重建的子视图、缓存数据等非必要资源。示例代码:- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // 视图未显示时清理资源 if (!self.view.window) { self.customChartView = nil; self.tempImageCache = nil; } } - dealloc 做最终清理:对于和控制器生命周期绑定的资源(比如通知监听、定时器),直接在
dealloc中完成最终清理,ARC 下无需手动调用[super dealloc]。 - 弱引用自动回收:对视图控件尽量用
__weak弱引用声明,这样当视图被系统回收时,相关引用会自动置空,避免不必要的内存占用。
二、切换视图时注销通知监听的正确方法
你试的几个方法没生效,大概率是场景没匹配对或者代码存在细节问题,我分两种常见场景给你梳理:
场景1:控制器暂时隐藏(如Tab切换、弹出Modal控制器)
这种情况下控制器并未被销毁,只是视图不可见,应该用 viewWillDisappear: 和 viewWillAppear: 配对处理——消失时注销通知,重新显示时再注册,保证切换回来后能正常接收通知。示例代码:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUserLogin:) name:@"UserLoginSuccess" object:nil]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UserLoginSuccess" object:nil]; }
如果这个方法没生效,先检查是否调用了 [super viewWillDisappear:],或者是不是通知名称、选择器拼写错误。
场景2:控制器即将被销毁(如导航栈Pop、Modal Dismiss后销毁)
这种情况下 dealloc 是最可靠的清理点,只要控制器没有循环引用,dealloc 一定会被执行。如果你的 dealloc 没触发,大概率是存在循环引用:比如通知的 block 里直接捕获 self 未用弱引用,或者定时器、网络请求持有了 self。示例代码:
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; // 同步清理其他绑定资源 [self.updateTimer invalidate]; self.updateTimer = nil; }
另外,willMoveToParentViewController: 也可以用来判断控制器是否被移除——当 parent 参数为 nil 时,说明控制器即将被从父容器中移除,此时也可以注销通知:
- (void)willMoveToParentViewController:(UIViewController *)parent { [super willMoveToParentViewController:parent]; if (!parent) { [[NSNotificationCenter defaultCenter] removeObserver:self]; } }
如果还是没效果,建议给这些方法打个断点,确认方法是否真的被调用,排查下控制器的生命周期是否和你预期一致。
内容的提问来源于stack exchange,提问作者Student
相关产品推荐
相关产品推荐

