zl程序教程

您现在的位置是:首页 >  其他

当前栏目

iOS - 记录一次内存泄漏

2023-04-18 14:39:43 时间

一· 屋漏偏逢连夜雨(全都漏了)

起因 :

因有需求需要绑定微信账号并对接微信SDK时候发现

1. 调用sendReq 
[WXApi sendReq:req completion:^(BOOL success) {
            
 }];
 
 2. 接收到回调 此方法只在Appdelegate.m 处出发 因为sdk在初始化时候注册 [WXApi registerApp:WECHAT_APPID universalLink:UNIVERSALLINK];
 - (void)onResp:(BaseResp *)resp{ 
 }

问题发现:

发现经过 由于业务需求需要有绑带微信&登录微信两个功能 实际上访问的是同一个登陆接口路由

由于微信sdk回调 onResp只在Appdelegate.m , 那么解决方案我选择KVO 。

当我调用sdk-确认授权-触发回调的时候 KVO这两个登录和绑定监听同时触发

    [[NSNotificationCenter defaultCenter] postNotificationName:@"weChatLoing" object:dict];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"weChatBinding" object:dict];

问题分析:

基本上确定上内存泄漏,问题是泄漏点在哪,自此开始了漫长的排查

尝试解决:

从dealloc开始入手

- (void)dealloc {
 [[NSNotificationCenter defaultCenter] removeObserver:self]; //打断点
}

考虑到当前对象既vc无法准确定位到内存泄漏到地方 只能从生命周期开始入手一个一个地方找

viewDidload

- (void)viewDidLoad {
    [super viewDidLoad];
    [self 网络请求];
    [self initUI];
    [self 登录:@"1" 密码:@"1"];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(登录监听) name:@"微信监听" object:nil];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(绑定监听) name:@"绑定监听" object:nil];
    [self 三分SDK初始化];
}

找到问题关键

         [AgoraRtm classMethod:Token user:uid completion:^(AgoraRtmLoginErrorCode errorCode) {
                    if (errorCode == AgoraRtmLoginErrorOk || errorCode == AgoraRtmLoginErrorAlreadyLogin) {
                        [AgoraRtm setStatus:LoginStatusOnline];
                    }else{
                    }
                }];

最终定位到自己定义的声网sdk类方法setStatus

内存泄漏点(二)

configure.customAreaView = ^(UIView * _Nonnull customAreaView) {
        UIButton *btn = [[UIButton alloc]init];
        btn.frame = CGRectMake(0,0,self.view.bounds.width,200);
        [btn addTarget:self action:@selector(fff) forControlEvents:UIControlEventTouchUpInside];
}

泄漏原因排查:

初步排查原因于button控件添加target的时候对当前对象引用,但同时SDK内部猜测可能有Runtime持有当前对象或者是异步并发线程处理数据时候也引用了当前对象,导致sdk内部自定义的customAreaView中添加button的target时导致内存泄漏,解决办法变成WeakSelf弱引用即可。

内存泄漏点(三)

原因排查: 当前对象对自定义弹框引用

解决办法:解偶

- (diyView *)diy {
    if (!_diy) {
        _diy = [[diyView alloc]init];
        _diy.delegate = self;
        _diy.frame = CGRectMake(0, 0, 200, 200);
    }
    return _diy;

结论:由于弹框使用时机不确定,当时选择作为一个对象懒加载进来的想法是错误的,代码需要保持一定的整洁,尽可能做到减少self的使用,以达到接偶的目的,此次泄漏情况的原因是由于sdk类方法定义失误导致后继代码使用self的地方一并泄漏

内存泄漏点(四)

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kvo) name:@"kvo" object:nil];

在dealloc处remove监听不要以为就万事大吉.此处内存泄漏狠狠地打了我一脸

结论:KVO/KVC 监听需要满足情况下才能使用。1.对当前对象对生命周期足够把握 2.尽可能不使用监听 因为内存泄漏十有八九是kvo block 这些会延长生命周期的方法