1. 视图控制器创建和销毁时的内存管理
- 避免强引用循环:
- 在视图控制器与模型对象之间,确保引用关系合理。通常视图控制器持有模型对象的强引用是合理的,因为视图控制器负责加载数据到模型。但模型对象不应反向强引用视图控制器,以防止循环引用导致内存泄漏。例如,如果模型对象有一个属性指向视图控制器,应将其声明为
weak
引用(在Objective - C中)。
- 在视图控制器与视图之间,视图控制器对视图通常是强引用。但在视图与视图控制器交互时(如按钮点击回调等),视图不应强引用视图控制器,也应使用
weak
引用。
- 释放资源:
- 在视图控制器的
dealloc
方法中,释放所有由视图控制器创建的临时资源,如取消所有正在进行的网络请求。在iOS开发中,可使用NSURLSession
的dataTask
来进行网络请求,在视图控制器销毁前调用cancel
方法取消任务。例如:
@interface ViewController ()
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@end
@implementation ViewController
- (void)dealloc {
[self.dataTask cancel];
}
@end
2. 模型对象的正确释放
- 对象生命周期管理:
- 当视图控制器销毁时,由于其对模型对象是强引用,若没有其他对象强引用模型对象,模型对象会随着视图控制器的销毁而被释放。但如果在应用的其他地方有对模型对象的强引用,需要确保在合适的时候释放这些引用,让模型对象能够被正确释放。
- 例如,如果有一个全局的缓存机制持有模型对象的强引用,在视图控制器销毁时,需要从缓存中移除该模型对象的引用。
- 自动释放池:
- 如果在加载网络数据过程中创建了大量临时对象,可使用自动释放池来优化内存使用。例如,在解析网络数据并创建模型对象的方法中:
- (void)parseData:(NSData *)data {
@autoreleasepool {
// 解析数据并创建模型对象的代码
// 这里创建的临时对象会在自动释放池结束时被释放
}
}
3. 结合设计模式优化内存管理
- 单例模式:
- 实现思路:如果某些模型对象的数据在整个应用中是共享的,且不需要频繁创建和销毁,可以将其设计为单例模式。在Objective - C中实现单例可通过
dispatch_once
来确保单例对象只被创建一次。例如:
@interface SharedModel : NSObject
@property (nonatomic, strong) NSString *sharedData;
+ (instancetype)sharedInstance;
@end
@implementation SharedModel
+ (instancetype)sharedInstance {
static SharedModel *sharedModel = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedModel = [[SharedModel alloc] init];
});
return sharedModel;
}
@end
- 可能遇到的问题:单例对象由于其生命周期与应用相同,可能会导致内存占用过高。特别是如果单例对象持有大量数据或资源,在应用长时间运行时可能会影响性能。另外,如果单例对象持有对视图控制器等有生命周期限制对象的强引用,可能会导致这些对象无法被释放,引发内存泄漏。
- 代理模式:
- 实现思路:在视图控制器与模型对象交互中,可使用代理模式来避免强引用循环。例如,模型对象可以有一个代理属性,当模型数据更新时,通过代理通知视图控制器,而不是直接持有视图控制器的引用。代理属性通常声明为
weak
,这样模型对象不会阻止视图控制器的释放。
- 可能遇到的问题:如果代理设置不正确,如没有及时设置或移除代理,可能会导致空指针异常。例如,视图控制器销毁前没有将其在模型对象中的代理设置为
nil
,模型对象在后续调用代理方法时可能会因为代理对象已被释放而导致程序崩溃。