在 iOS 开发中 内存泄漏是常见的问题, 这里整理下常用的内存检测方法.
使用XCode分析功能,Product->Analyze
使用静态检测可以检查出一些明显的没有释放的内存,包括NSObject和CF开头的内存泄漏.
缺点: 不能检测block导致的内存泄漏问题
使用 instruments
重写dealloc 方法, 在界面返回或者对象销毁的时候, 判断是否调用
MLLeaksFinder
我们根据这个原理, 简单实现一个自己简易的内存检测工具:
(1) 用runtime的技术交换 viewController 的 viewWillAppear 和 viewDidDisappear;
(2) 在viewWillAppear 中将标志位设为 NO, 代码如下:
- (void)sw_viewWillAppear:(BOOL)animated{
[self sw_viewWillAppear:animated];
objc_setAssociatedObject(self, &kLeakMemory, @(NO), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
(3) 交换 navigationController 的 popViewControllerAnimated, 并在其中将标志位设为YES
- (nullable UIViewController *)sw_popViewControllerAnimated:(BOOL)animated{
UIViewController *vc = [self sw_popViewControllerAnimated:animated];
extern const char *kLeakMemory;
objc_setAssociatedObject(self, &kLeakMemory, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return vc;
}
(4) 在viewController的viewDidDisappear中判断标志位, 并延时检测dealloc是否调用
- (void)sw_viewDidDisappear:(BOOL)animated{
[self sw_viewDidDisappear:animated];
if (objc_getAssociatedObject(self, &kLeakMemory)) {
[self willDealloc];
}
}
- (BOOL)willDealloc {
if (![super willDealloc]) {
return NO;
}
return YES;
}
/**super willDealloc*/
- (BOOL)willDealloc{
// 这里注意, 使用weakSelf 防止引起循环引用
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf showMsg:NSStringFromClass([strongSelf class])];
});
return YES;
}
- (void)showMsg:(NSString *)msg{
UIAlertView *alertViewTemp = [[UIAlertView alloc] initWithTitle:@"Leak"
message:msg
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alertViewTemp show];
}
Demo
如有疑问, 欢迎指出.