AFN的内存泄漏问题

3,858 阅读1分钟

在使用instruments做内存泄漏分析时,发现所有使用如下语句的地方都有内存泄漏,OMG:

leaks上图:

if (!_manager) {
    _manager = [AFHTTPSessionManager manager];
}

原因:session在ARC下不会及时释放

我所用到的网络请求不是很复杂,不想再新建类去写单例了,就把单例放在了AppDelegate中,用到的时候在通过AppDelegate拿。因为需要用到AFURLSessionManager,所以就写一个单例方法。

static AFHTTPSessionManager *manager ;`
-(AFHTTPSessionManager *)sharedHTTPSession{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [AFHTTPSessionManager manager];
        manager.requestSerializer.timeoutInterval = 10;
    });
    return manager;
}

但是 做成单例并不是很好的方式,可以在AFAppDotNetAPIClient中的dealloc中手动触发sessionManager.session.finish...()释放session的delegete,打破AF内部的循环引用

完美解决 @·@
原因探究: AFURLSessionManager实现了NSURLSession的协议,即AFURLSessionManagerNSURLSession互相持有,如果这个delegate是week的话,那没什么问题,但是系统提供的是retain:如图

NSURLSession

所以里面是有循环引用的。一旦使用非单例的方式来使用AFHTTPSessionManager,如果不做特殊处理,就会导致这个对象在应用存活期间是不会销毁的,如果应用网络请求过多,用户反复进入各种vc,内存泄漏明显。这明显不安全。

好在AFN和NSURLSession都有方法可以解决:

//废弃session对象。cancelPendingTasks决定是否取消此session中的tasks
–(void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks 

方法二:

__weak typeof(manager) weak_manager = manager;
    [manager requestWithMethod:method
        URLString:uri
        parameters:param
        success:^(NSURLSessionDataTask *task, id responseObject) {
            if (completion) {
                completion(YES, responseObject, task.response);
            }
            [weak_manager invalidateSessionCancelingTasks:YES];
        }
        failure:^(NSURLSessionDataTask *task, NSError *error) {
            if (completion) {
                completion(NO, error, task.response);
            }
            [weak_manager invalidateSessionCancelingTasks:YES];
        }];