面试题答案
一键面试1. 视图控制器生命周期方法与避免内存泄漏
- loadView:
- 此方法用于创建视图控制器的视图。如果手动创建视图,应避免强引用循环。例如,不要在
loadView
中让视图对视图控制器产生强引用。比如,自定义视图类中不应有类似@property (nonatomic, strong) MyViewController *viewController;
这样会导致循环引用的属性,并在loadView
中赋值。 - 如果从 nib 文件加载视图,确保 nib 文件中的对象关系正确,避免出现强引用循环。
- 此方法用于创建视图控制器的视图。如果手动创建视图,应避免强引用循环。例如,不要在
- viewDidLoad:
- 初始化视图相关的属性和数据。但要注意,对于添加到视图的子视图或设置的代理等,不要形成强引用循环。例如,设置代理时应使用
weak
或unsafe_unretained
(不推荐unsafe_unretained
,有悬空指针风险)。比如,self.tableView.delegate = self;
这里tableView
不应强引用self
,应确保tableView
的delegate
属性是weak
类型。 - 对于注册的通知,要在视图控制器销毁时移除。例如,
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"SomeNotification" object:nil];
要在dealloc
方法中[[NSNotificationCenter defaultCenter] removeObserver:self name:@"SomeNotification" object:nil];
,否则会导致视图控制器无法释放而内存泄漏。
- 初始化视图相关的属性和数据。但要注意,对于添加到视图的子视图或设置的代理等,不要形成强引用循环。例如,设置代理时应使用
- viewWillAppear:
- 在这里进行与视图即将显示相关的操作,如更新界面数据等。避免创建不必要的强引用对象,如果创建了临时对象,要确保它们在合适的时候被释放。例如,不要在
viewWillAppear
中创建一个强引用的临时视图并一直持有,导致视图控制器无法释放。
- 在这里进行与视图即将显示相关的操作,如更新界面数据等。避免创建不必要的强引用对象,如果创建了临时对象,要确保它们在合适的时候被释放。例如,不要在
- viewDidAppear:
- 同样,避免在这里创建可能导致强引用循环或内存泄漏的对象。如果有动画等操作,确保动画完成后相关对象能正确释放。例如,使用
CAAnimation
时,设置anim.delegate = self;
要在动画结束时清理相关引用,否则可能导致循环引用。
- 同样,避免在这里创建可能导致强引用循环或内存泄漏的对象。如果有动画等操作,确保动画完成后相关对象能正确释放。例如,使用
2. 视图控制器嵌套时的特殊处理
- 导航控制器(UINavigationController):
- 当视图控制器压入导航控制器栈时,导航控制器会对其产生强引用。确保从导航控制器栈弹出视图控制器时,视图控制器中的资源能正确释放。比如,对于弹出视图控制器时正在进行的网络请求,要取消请求,避免视图控制器无法释放。可以在
viewWillDisappear
方法中取消网络请求,例如使用AFNetworking
时,[self.dataTask cancel];
- 不要在导航控制器的子类中对某个视图控制器形成不合理的强引用。例如,导航控制器子类不应有
@property (nonatomic, strong) MyViewController *specificViewController;
并一直持有,导致该视图控制器无法释放。
- 当视图控制器压入导航控制器栈时,导航控制器会对其产生强引用。确保从导航控制器栈弹出视图控制器时,视图控制器中的资源能正确释放。比如,对于弹出视图控制器时正在进行的网络请求,要取消请求,避免视图控制器无法释放。可以在
- 标签栏控制器(UITabBarController):
- 标签栏控制器会强引用其包含的视图控制器。当切换标签时,要确保不再显示的视图控制器能正确释放资源。例如,对于视图控制器中的定时器,在
viewWillDisappear
中停止并释放定时器,[self.timer invalidate]; self.timer = nil;
- 避免在标签栏控制器的子类中对某个子视图控制器形成不合理的强引用,导致子视图控制器无法释放。同时,要注意子视图控制器之间的关系,避免出现循环引用。例如,两个子视图控制器之间互相强引用对方,应使用
weak
引用来打破循环。
- 标签栏控制器会强引用其包含的视图控制器。当切换标签时,要确保不再显示的视图控制器能正确释放资源。例如,对于视图控制器中的定时器,在