系统默认内存管理机制
- ARC(自动引用计数):在ARC模式下,编译器会自动为对象的生命周期管理插入引用计数相关的代码。例如,当一个视图控制器被创建时,其引用计数为1。当通过
push
或present
操作将其展示在屏幕上时,相关对象(如导航控制器对被push
的视图控制器的引用,或者presentingViewController
对被presentedViewController
的引用)会使该视图控制器的引用计数增加。当视图控制器被pop
或dismiss
时,相关引用被移除,引用计数减少。当引用计数变为0时,对象被自动释放。
- MRC(手动引用计数):在MRC模式下,开发者需要手动管理对象的引用计数。使用
retain
方法增加引用计数,使用release
方法减少引用计数,autorelease
方法会将对象添加到自动释放池,在自动释放池被销毁时减少对象的引用计数。例如,在push
一个视图控制器时,开发者需确保在合适的时机手动管理其引用计数,避免过早或过晚释放。
避免内存泄漏或过度释放的方法
- ARC下的注意事项
- 强引用循环:避免在视图控制器之间创建强引用循环。例如,不要在父视图控制器中对一个子视图控制器进行强引用,同时子视图控制器又对父视图控制器进行强引用。可以使用
weak
关键字来打破这种循环引用。比如,在自定义的容器视图控制器中,如果子视图控制器需要引用父视图控制器,可以将这个引用声明为weak
:
@property (nonatomic, weak) ParentViewController *parentVC;
- 代理模式:在使用代理模式时,代理属性应声明为
weak
,以防止循环引用。例如,一个视图控制器遵守某个协议并作为另一个视图控制器的代理,应这样声明代理属性:
@property (nonatomic, weak) id<SomeProtocol> delegate;
- MRC下的注意事项
- 正确的引用计数操作:确保在合适的时机调用
retain
、release
和autorelease
方法。例如,在创建一个视图控制器对象后,如果要将其传递给其他对象(如导航控制器进行push
操作),要注意对象的所有权转移,确保不会过度释放。
- 自动释放池的使用:合理使用自动释放池,特别是在循环中创建大量临时对象时。例如:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i = 0; i < 1000; i++) {
MyViewController *vc = [[MyViewController alloc] init];
// 对vc进行操作
[vc autorelease];
}
[pool drain];
自定义视图控制器转换动画时的内存管理风险点及解决方案
- 风险点
- 动画相关对象的强引用循环:当自定义动画时,可能会在动画对象和视图控制器之间创建强引用循环。例如,在自定义过渡动画代理类中,如果对视图控制器进行了强引用,同时视图控制器又对这个代理类进行强引用,就会导致内存泄漏。
- 过渡完成后未清理资源:在自定义动画完成后,如果没有正确地释放或移除在动画过程中创建的临时对象(如自定义的过渡视图),可能会导致内存泄漏。
- 解决方案
- 打破强引用循环:在自定义过渡动画代理类中,对视图控制器的引用应声明为
weak
。例如:
@property (nonatomic, weak) UIViewController *viewController;
- 清理过渡资源:在过渡动画完成的回调方法中,确保清理所有在动画过程中创建的临时对象。例如,如果在自定义过渡中创建了一个过渡视图,在动画完成后应将其从父视图中移除并释放相关资源:
- (void)animationEnded:(BOOL)transitionCompleted {
[self.transitionView removeFromSuperview];
self.transitionView = nil;
}