iOS快速有效的解决内存泄露
2019-02-01 本文已影响0人
正义从不缺席
1.使用xcode的Debug Memory Graph来查看内存引用关系
以下代码,很明显的循环引用:viewController引用object, object通过delegate引用viewController
@interface MyObject : NSObject
@property (nonatomic, strong) id delegate;
@end
@implementation MyObject
@end
@interface ViewController ()
@property (nonatomic, strong) MyObject *object;
@end
@implementation ViewController
- (void)dealloc {
NSLog(@"%s", __func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
_object = [MyObject new];
_object.delegate = self;
}
@end
我们打开Debug Memory Graph来看一下:


可以很明显看到对象的引用关系,从而解决内存泄露,如果viewController被一个block强引用住,看看结果是怎样:
- (void)viewDidLoad {
[super viewDidLoad];
// 理论上10000000s后 viewController才会被释放
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10000000 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.view.backgroundColor = UIColor.redColor;
});
}
Debug Memory Graph结果:

⤴️⤴️⤴️⤴️⤴️只知道被一个block引用住了,但具体是哪个block,代码在哪里?无法查找。对于这种问题我们可以尝试使用Instruments
2.使用Instruments来查找内存泄露
接着上面的问题
1.将Build Setting->Debug Information Format->Debug设置为DWARF with sSYM File,重新run app
2.打开Xcode->Open Developer Tool-> Instruments选择Leaks
选择需要调试的app,点击小红点,开始记录

复现刚刚的内存泄露,搜索泄露的类

点击箭头

继续

ok,到了最后一步, 这里就是这个对象的内存引用历史记录了

通过观察,我们不难发现上面的retain和release都是成对出现的,最后一步只有retain没有release操作,这一就是导致未释放的原因,可以看到是viewDidLoad方法触发的,刚好与我们的垃圾代码相吻合😂