前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS - 记录一次内存泄漏

iOS - 记录一次内存泄漏

原创
作者头像
Wilbur-L
发布2021-12-08 08:55:28
5930
发布2021-12-08 08:55:28
举报
文章被收录于专栏:iOS底层原理iOS底层原理

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

起因 :

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

代码语言:javascript
复制
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这两个登录和绑定监听同时触发

代码语言:javascript
复制
    [[NSNotificationCenter defaultCenter] postNotificationName:@"weChatLoing" object:dict];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"weChatBinding" object:dict];

问题分析:

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

尝试解决:

从dealloc开始入手

代码语言:javascript
复制
- (void)dealloc {
 [[NSNotificationCenter defaultCenter] removeObserver:self]; //打断点
}

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

viewDidload

代码语言:javascript
复制
- (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初始化];
}

找到问题关键

代码语言:javascript
复制
         [AgoraRtm classMethod:Token user:uid completion:^(AgoraRtmLoginErrorCode errorCode) {
                    if (errorCode == AgoraRtmLoginErrorOk || errorCode == AgoraRtmLoginErrorAlreadyLogin) {
                        [AgoraRtm setStatus:LoginStatusOnline];
                    }else{
                    }
                }];

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

内存泄漏点(二)

代码语言:javascript
复制
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弱引用即可。

内存泄漏点(三)

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

解决办法:解偶

代码语言:javascript
复制
- (diyView *)diy {
    if (!_diy) {
        _diy = [[diyView alloc]init];
        _diy.delegate = self;
        _diy.frame = CGRectMake(0, 0, 200, 200);
    }
    return _diy;

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

内存泄漏点(四)

代码语言:javascript
复制
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kvo) name:@"kvo" object:nil];

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

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一· 屋漏偏逢连夜雨(全都漏了)
    • 起因 :
      • 问题发现:
        • 问题分析:
          • 尝试解决:
            • 从dealloc开始入手
            • viewDidload
            • 找到问题关键
          • 内存泄漏点(二)
            • 泄漏原因排查:
          • 内存泄漏点(三)
            • 原因排查: 当前对象对自定义弹框引用
            • 结论:由于弹框使用时机不确定,当时选择作为一个对象懒加载进来的想法是错误的,代码需要保持一定的整洁,尽可能做到减少self的使用,以达到接偶的目的,此次泄漏情况的原因是由于sdk类方法定义失误导致后继代码使用self的地方一并泄漏
            • 内存泄漏点(四)
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档