从一个AFNetworking循环引用说起

简介: 本文分析使用代码是AFNetworking 3.2.1最近使用Instruments中的Leaks分析项目内存泄露,发现了一个AFNetworking的循环引用。

本文分析使用代码是AFNetworking 3.2.1

最近使用Instruments中的Leaks分析项目内存泄露,发现了一个AFNetworking的循环引用。如下图所示:

img_d87589dbb97ad7ef55d400d164597e7f.jpe
15354171666142.jpg

通过调用栈发现产生泄露的代码在这里:

// AFURLSessionManager.m
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    // ... 初始化代码,省略

    // 导致循环引用的方法
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

    // ... 其它初始化代码,省略
    return self;
}

大致原因就是AFURLSessionManager引用NSURLSession,同时设置NSURLSession的delegate为自己,NSURLSession会强引用delegate,于是产生了循环引用。

关于NSURLSession的delegate官方说明:
This delegate object is responsible for handling authentication challenges, for making caching decisions, and for handling other session-related events. The session object keeps a strong reference to this delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session, your app leaks memory until it exits.

解决方案

在AFNetworking官方issues找到了相关的问题Possible memory leak in AFURLSessionManager。作者的回答如下:

img_0732f7735e1a9c2531bc6f4800488303.jpe
15353328585634.jpg

解决方案有两种:

  1. 这是最常见也是作者推荐的方法,只创建一个AFURLSessionManager,整个APP共享,虽然还是有循环引用,但是就没有内存泄露的问题了。
  2. 如果要使用多个AFURLSessionManager,在使用完成后手动调用invalidateSessionCancelingTasks:来断开循环引用。(这种方案不推荐,具体原因看下一小节)

AFURLSessionManager复用

关于AFURLSessionManager是否使用单例这个问题,官方demo使用的是单例,在苹果官方文档找到这么一段话

With the NSURLSession API, your app creates one or more sessions, each of which coordinates a group of related data transfer tasks. For example, if you’re creating a web browser, your app might create one session per tab or window, or one session for interactive use and another for background downloads. Within each session, your app adds a series of tasks, each of which represents a request for a specific URL (following HTTP redirects, if necessary).

我的理解是这样的,根据使用场景的不同,这个问题有不同的答案,在大多数场景下APP都是在和同一服务器打交道,一个session就够了,如果有连接多个服务器、或者后台下载等功能需求,可以给每个服务器、后台下载任务创建单独的session(但是也不能每个请求都单独创建session)。

在查找资料的时候,我发现有博客提到单例seesion可以减少TCP三次握手,动手验证下:

多个网络请求复用一个AFURLSessionManager,连续发两个网络请求,用Wireshark抓包可以看到,第二次网络请求复用了第一次的TCP连接,没有做三次握手。

img_2a35c0f5d09e53b81f436f7b80714c7d.jpe
15354191775340.jpg

下图是每次网络请求都新建一个AFURLSessionManager的抓包,可以看到每个网络请求都进行了TCP三次握手。

img_3b3b81c94702561a587e1ef98d61ce45.jpe
15354193039698.jpg

实验结果的确如网上所说,复用AFURLSessionManager可以减少三次握手,提升效率。

博客链接

目录
相关文章
|
iOS开发 编译器 JavaScript
iOS八种内存泄漏问题
循环引用(Retain Cycle) 先简单说一下什么是循环引用(retain cycle) ​假设我们有两个实例A和B,B是A的一个strong型的property,则B的引用计数是1,当A的需要释放的时候,A则会调用[B release]来释放B,B的引用计数则减为0,释放。
2612 0
|
API iOS开发
iOS面试关于runtime
iOS面试关于runtime
275 0
|
弹性计算 Shell 网络安全
因为 /usr/bin/dbus-daemon 共享库文件引发的系统启动异常
因为 /usr/bin/dbus-daemon 共享库文件引发的系统启动异常
|
29天前
|
数据采集 人工智能 供应链
2025医药行业Agent案例:从研发到终端的8大场景+15个标杆实践
AIAgent正深度重构医药行业,覆盖研发、生产、医疗、营销等八大场景。六周完成晶体结构确认、诊断建议与专家一致性超98%、7×24小时精准处理订单……15个标杆案例揭示:Agent已从概念落地为核心生产力,推动新药研发提速30%,年复合增长率达42%。
|
机器学习/深度学习 人工智能 自然语言处理
人工智能技术在金融领域的应用有哪些?
【10月更文挑战第16天】人工智能技术在金融领域的应用有哪些?
4373 1
|
JavaScript 前端开发 API
vite中如何根据不同环境配置打包规则?一个if语句即可搞定!
【8月更文挑战第1天】vite中如何根据不同环境配置打包规则
852 5
vite中如何根据不同环境配置打包规则?一个if语句即可搞定!
|
存储 算法 安全
如何在Java中实现加密解密
如何在Java中实现加密解密
|
NoSQL 安全 前端开发
验证码倒计时:用户界面的小细节,大智慧
本文深入探讨了验证码倒计时的设计和实现,一项看似简单但对用户体验影响深远的功能。我们将讨论为什么需要倒计时,如何在不同平台(如Web和移动应用)上实现它,以及如何确保它既用户友好又安全。无论你是前端新手还是资深开发者,理解验证码倒计时的原理和最佳实践都将有助于你创建更流畅、更安全的用户界面。
702 3
|
算法 调度 芯片
RT-Thread快速入门-线程管理
RT-Thread快速入门-线程管理
401 0
RT-Thread快速入门-线程管理