美文网首页iOS经验总结
关于项目中两个内存泄露问题的解决

关于项目中两个内存泄露问题的解决

作者: mark666 | 来源:发表于2018-06-27 18:30 被阅读113次

    最近跳槽一家新公司,接手了以前的一个4年的老项目,传言中间有4个以上的人接手过,这中间代码质量也是没有任何把控的,所以为了提升系统健壮性,在完成项目新需求的同时进行着性能的优化,最近可能更多的记录一些优化方面的东西,这篇文章展示两个内存的泄露的例子:

    1.NSDate

         NSDate *date = [[NSDate alloc] init];
         date = [date initWithTimeIntervalSince1970:42];
    
         NSDate *date = [NSDate date];
         date = [date initWithTimeIntervalSince1970:42];
    

    很多人在创建date 不注意这一点,上述两种方式创建方式都会造成内存泄露,我们通过instruments 定位到泄露情况:

    而 产生错误的原因很简单,新生成一个 date 对象,用date 指向生成的这个对象,此时这个对象的引用计数为1, 然后[date initWithTimeIntervalSince1970:42] 这个也会生成一个新的对象,date 指向这个对象,这个对象引用计数也为1,当出了作用域,date销毁了,第二次产生对象也随之销毁,而第一次产生的对象是无法销毁的,引用计数始终为1.

    所以我们通常正确的创建的方式是生成并持有一个对象,避免产生多个无法访问的对象

    NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:42]
    

    这样就不会产生内存泄露。

    2.AFNetworking 使用问题

    很多人在使用 AFNetworking 时候可能没有关注过这个问题,错误的使用AFNetworking 进行网络请求而导致内存泄露。

    - (void)GET:(NSString *)url
            parameters:(NSDictionary *)param
            success:(void (^)(id _Nullable requestData))success
            failure:(void (^)(NSError  * _Nullable  error))failure{
    
        AFHTTPSessionManager *operationManage = [AFHTTPSessionManager manager];
        operationManage.requestSerializer = [AFJSONRequestSerializer serializer];
        operationManage.responseSerializer = [AFJSONResponseSerializer serializer];
    
        [operationManage GET:url parameters:param progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        }];
    
    

    有的人不注意这个细节,每次请求都会重新创建一个 AFHTTPSessionManager , 这样就会导致内存泄露,具体的大家可以通过工具查看一下泄露的产生,我查看了一下网上,大家的通常说封装成一个单例就好了,很多人可能不太了解这个原因,以及为什么要这样做,我大概解释一下,大家就明白了这个原因

    首先AFHTTPSessionManager 我们通过 manager获取其实例的, 并且 是继承于 AFURLSessionManager, 而 AFURLSessionManager 中一个会话对象NSURLSession *session,而这个对象创建时候有一个代理属性是 retain,当你重新再发一次网络请求时候,上一次NSURLSession *sessiondelegate 产生循环引用无法被释放了,除非你主动调用一下 '[mgr.session invalidateAndCancel]',这样才可以释放掉。

    这样你就很容易理解内存泄露问题的根源了,解决起来就容易了

    解决方案一

    通过网上大众做法封装成一个单例,获取封装成一个static 变量在网络封装类initialize中初始化, 当然这种方式你得确保你URL和参数设置的请求头是一致的,如果不一致,这样做肯定是不可以的。

    解决方案二

    每次请求结束主动调用一次取消

    [operationManage.session invalidateAndCancel];
    

    这样就能够解决了这种内存泄露。

    相关文章

      网友评论

        本文标题:关于项目中两个内存泄露问题的解决

        本文链接:https://www.haomeiwen.com/subject/xzfiyftx.html