写点什么

iOS 性能优化 — 四、内存泄露检测

用户头像
iOSer
关注
发布于: 2020 年 11 月 08 日
iOS性能优化 — 四、内存泄露检测

上篇文章为大家讲解了安装包瘦身,这篇文章继续为大家讲解下内存泄露检测。



  • 造成内存泄漏原因

  • 常见循环引用及解决方案

  • 怎么检测循环引用

造成内存泄漏原因



  • 在用C/C++时,创建对象后未销毁,比如调用malloc后不free、调用new后不delete;

  • 调用CoreFoundation里面的C方法后创建对对象后不释放。比如调用CGImageCreate不调用CGImageRelease;

  • 循环引用。当对象A和对象B互相持有的时候,就会产生循环引用。常见产生循环引用的场景有在VC的cellForRowAtIndexPath方法中cell block引用self。



常见循环引用及解决方案



1) 在VC的cellForRowAtIndexPath方法中cell的block直接引用self或者直接以_形式引用属性造成循环引用。



cell.clickBlock = ^{
self.name = @"akon";
};

cell.clickBlock = ^{
_name = @"akon";
};




解决方案:把self改成weakSelf;



__weak typeof(self)weakSelf = self;
cell.clickBlock = ^{
weakSelf.name = @"akon";
};




2)在cell的block中直接引用VC的成员变量造成循环引用。



//假设 _age为VC的成员变量
@interface TestVC(){

int _age;

}
cell.clickBlock = ^{
_age = 18;
};




解决方案有两种:



  • 用weak-strong dance



__weak typeof(self)weakSelf = self;
cell.clickBlock = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf->age = 18;
};




  • 把成员变量改成属性



//假设 _age为VC的成员变量
@interface TestVC()

@property(nonatomic, assign)int age;

@end

__weak typeof(self)weakSelf = self;
cell.clickBlock = ^{
weakSelf.age = 18;
};




3)delegate属性声明为strong,造成循环引用。



@interface TestView : UIView

@property(nonatomic, strong)id<TestViewDelegate> delegate;

@end

@interface TestVC()<TestViewDelegate>

@property (nonatomic, strong)TestView* testView;

@end

testView.delegate = self; //造成循环引用




解决方案:delegate声明为weak



@interface TestView : UIView

@property(nonatomic, weak)id<TestViewDelegate> delegate;

@end




4)在block里面调用super,造成循环引用。



cell.clickBlock = ^{
[super goback]; //造成循环应用
};




解决方案,封装goback调用



__weak typeof(self)weakSelf = self;
cell.clickBlock = ^{
[weakSelf _callSuperBack];
};

- (void) _callSuperBack{
[self goback];
}




5)block声明为strong

解决方案:声明为copy

6)NSTimer使用后不invalidate造成循环引用。

解决方案:



  • NSTimer用完后invalidate;

  • NSTimer分类封装




* (NSTimer *)ak_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)(void))block
repeats:(BOOL)repeats{

return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(ak_blockInvoke:)
userInfo:[block copy]
repeats:repeats];
}

* (void)ak_blockInvoke:(NSTimer*)timer{

void (^block)(void) = timer.userInfo;
if (block) {
block();
}
}

怎么检测循环引用



  • 静态代码分析。 通过Xcode->Product->Anaylze分析结果来处理;

  • 动态分析。用MLeaksFinder或者Instrument进行检测。



资料推荐



如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。





用户头像

iOSer

关注

微信搜索添加微信 mayday1739 进微信群哦 2020.09.12 加入

更多大厂面试资料进企鹅群1012951431

评论

发布
暂无评论
iOS性能优化 — 四、内存泄露检测