• 内存泄漏解一波


    1,AFNetWorking 内存泄漏

    原理:

    https://www.jianshu.com/p/4584ace111b2

    解决方法:

    网上很多文章都说AFNetWorking有内存泄漏问题,其实是使用者自己的问题,他们的解决方法是将AFHTTPSessionManager写成单例,用该单例进行网络请求。

    其实不然。AFHTTPSessionManager继承于AFURLSessionManager,AFURLSessionManager有个属性session,session类型是NSURLSession,调用NSURLSession进行请求后,等请求完毕后调用session的finishTasksAndInvalidate方法,或者调用取消session的invalidateAndCancel方法,再或者将session属性置成nil,这样AFURLSessionManager就能正常释放,这样就不需要将AFHTTPSessionManager写成单例来使用了。NSURLSession将代理属性delegate强引用了,所以NSURLSession影响了其delegate的释放,调用其中的一个invalidate方法时,就会将其delegate引用计数减一,这样其delegate就能正常释放了,这里的delegate就是AFURLSessionManager。

        service.task = [self.sessionManager POST:service.urlString parameters:service.dataDictionary progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject)
                        {
                            if (service.isShowLoadingView) [MBProgressHUD hideHUD];
                            //网络请求成功(包含过滤服务器定义的错误码操作,实现在子类)
                            [self responseHandler:responseObject service:service];
                            
                        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                            //网络请求错误处理操作
                            [service requestFail:ERROR_CODE_FAILURE errorMessage:REQUEST_FAILURE];
                            if (service.isShowLoadingView) [MBProgressHUD hideHUD];
                            //错误提示
                            NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
                            if (statusCode == 0)
                            {
                                statusCode = error.code;
                            }
                            [self requestFailWithService:service statusCode:statusCode];
    //                        NSLog(@"URL==>%@
    ErrorCode==>%d===ErrorMessage==>%@",service.urlString,ERROR_CODE_FAILURE,REQUEST_FAILURE);
                        }];
       [self.sessionManager.session finishTasksAndInvalidate];  //释放
    

      

    2,

    GSKeyChain

    将 原代码:

    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
        return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                       (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
                       service, (__bridge_transfer id)kSecAttrService,
                       service, (__bridge_transfer id)kSecAttrAccount,
                       (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
                       nil];
    }

    换成:

    static NSMutableDictionary * queryDIC;
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
       
        if (!queryDIC) {
            queryDIC =[NSMutableDictionary dictionaryWithObjectsAndKeys:
                       (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
                       service, (__bridge_transfer id)kSecAttrService,
                       service, (__bridge_transfer id)kSecAttrAccount,
                       (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
                       nil];
        }
        return queryDIC;
    }

    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service KeychainHelper内存泄露

    https://www.jianshu.com/p/4c1618c97410

    3,

    ///获取ssid
    + (NSString *)getWifiName
    {
        NSArray* ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
        id info = nil;
        for (NSString *ifnam in ifs){
            info = (__bridge id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
            
            if (info && [info count])
                break;
        }
        NSString *wifiname = info[@"SSID"];
        return UNNULL_STRING(wifiname);
    }
    

      

    id bridge  换成   CFBridgingRelease

    如:

    ///获取ssid
    + (NSString *)getWifiName
    {
        NSArray *ifs = CFBridgingRelease(CNCopySupportedInterfaces());
        id info = nil;
        for (NSString *ifnam in ifs){
            info = CFBridgingRelease(CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam));
            if (info && [info count])
                break;
        }
        NSString *wifiname = info[@"SSID"];
        return UNNULL_STRING(wifiname);
    }
    

      4 

    - (void)setModels
    {
        //获取当前类
        id infoClass = [self class];
        unsigned int count = 0;
        Ivar *members = class_copyIvarList([infoClass class], &count); //获取属性列表 
        for (int i = 0 ; i < count; i++) {  //遍历属性列表
            Ivar var = members[i];
            const char *memberType = ivar_getTypeEncoding(var); //获取变量类型
            NSString *typeStr = [NSString stringWithCString:memberType encoding:NSUTF8StringEncoding];
            //判断类型是否为字典——只处理物的模型中的属性
            if ([typeStr isEqualToString:@"@"NSDictionary""]) {
                const char *memberName = ivar_getName(var); //获取变量名称
                [self setModelWithDicName:[NSString stringWithCString:memberName encoding:NSUTF8StringEncoding] channel:IOTBaseModelValueChangedChannel_Get];
            }
        }
        free(members); //添加
    }
    

      

    Ivar *members = class_copyIvarList([infoClass class], &count); //获取属性列表 这句报了leak,加 free(members);  来释放掉。

    原理:Runtime方法中的class_copyIvarList,class_copyMethodList这些方法返回的对象没有被手动释放导致的内存泄漏。因为这些是C实现的函数,是需要手动对函数返回值进行free的,不然则会导致内存泄露。= =。这里也顺便提醒平时需要注意对于C/C++的实现,当见到malloc/new分配的对象,就应该检查该对象有没有对应的free/delete操作,这些地方往往也是内存泄漏产生的地方。

     
  • 相关阅读:
    GPT(4kb硬盘) 单硬盘装变色龙、GAH61MAD2V、ALC887VD、HD6570成功驱动经验(转)
    unable to dequeue a cell with identifier Cell must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
    2013.5.29
    平等博弈
    组合数学
    哈密顿+欧拉图
    差分约束
    11.11
    如何直接跳出多重循环
    摘要:数组练习与部分字符串练习
  • 原文地址:https://www.cnblogs.com/developer-qin/p/10292261.html
Copyright © 2020-2023  润新知