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来看一下:
09C6697F-D88B-454D-8B13-9367A54935AF.png 屏幕快照 2019-02-01 15.09.56.png可以很明显看到对象的引用关系,从而解决内存泄露,如果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结果:
AFCE4C42-8771-47B5-A473-4D0D166CC4BC.png⤴️⤴️⤴️⤴️⤴️只知道被一个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,点击小红点,开始记录
265D7414-6A64-410D-B1E5-458E55035E79.png复现刚刚的内存泄露,搜索泄露的类
E421A319-4124-48E5-9554-9C96CE6A8C10.png点击箭头
94C0F26A-B2F9-4849-82F0-4983BDFB4EF7.png继续
CE44A5E1-E757-4A9C-B583-97871A067D25.pngok,到了最后一步, 这里就是这个对象的内存引用历史记录了
2BA7C09F-ECCF-4D63-BD87-5EE219EFB14E.png通过观察,我们不难发现上面的retain和release都是成对出现的,最后一步只有retain没有release操作,这一就是导致未释放的原因,可以看到是viewDidLoad方法触发的,刚好与我们的垃圾代码相吻合😂
网友评论