[iOS] AFNetworking 的内存泄漏分析

本文分析了使用 AFNetworking 组件时遇见的内存泄漏问题的根本原因,并给出解决方案。

当第一次学会使用 Leaks 时,便拿了公司的 APP 项目练手测试了一下。结果测试刚开始,便出现了 Leaks 经典的小红叉。查看了一下小红叉的原因,就是 AFNetworking。由于 APP 在启动时,需要使用 AFNetworking 请求并下载相关的资源更新。当时并没有对这个小红叉的成因继续深究下去,趁最近有空,回过头来研究一下。

1. Demo 测试

编写一个 Demo,复现一下当时内存泄漏的情况。AFNetworking 的版本为 3.2.1。

#import "ViewController.h"
#import <AFNetworking.h>

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    button.frame = CGRectMake(0, 0, 100, 50);
    button.center = self.view.center;
    [button setTitle:@"Request" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(requestButtonEvent) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)requestButtonEvent {
    NSString *url = @"https://www.baidu.com";
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    [manager GET:url parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"%@", responseObject);
        NSLog(@"%@", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"Error: %@", error);
    }];
}

@end

每当点击一次 Request 按钮,就会调用 AFNetworking 的 get 接口请求百度首页。然后,使用 Leaks 来查看一下内存泄漏的情况。

 在 Leaks 的图中,可以看出每点击一次 Request 按钮,内存就会上涨一次,而且附带着内存泄漏的情况发生。查看下方的 Cycles & Roots,可以看到总共有两个引用环存在,刚好对应两次点击 Request 事件。

查看这两个引用环的场景,发现原因都是相同的。AFHTTPSessionManager 对象强引用 NSURLSession 类型的变量 _session,NSURLSession 类通过 delegate 强引用 AFHTTPSessionManager 对象。这个引用环的存在,导致 AFHTTPSessionManager 对象和 NSURLSession 对象都无法释放,造成了内存泄漏。

2. 内存泄漏原因分析

与常见的 Block 造成的循环引用不同,这是由 Delegate 造成的循环引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值