NSURLSession是苹果公司在Foundation框架的URL加载系统(URL Loading System)中提供的一套网络请求应用程序接口,用于在iOS、macOS、tvOS、watchOS等平台上通过URL与服务器交换数据。它既可以向内存返回数据,也可以把文件直接下载到磁盘,还能在应用未运行或处于挂起状态时完成后台上传与下载。该接口在2013年苹果全球开发者大会上随iOS 7一同发布,用以取代此前的NSURLConnection,现已成为苹果平台原生网络访问的基础组件,也是AFNetworking、Alamofire、SDWebImage等第三方网络库的底层实现。
定义
NSURLSession指代的不只是同名的一个类,而是苹果Foundation框架URL加载系统中一组相互关联的类与协议的总称。它负责通过URL访问网络资源,支持https等标准协议以及开发者自行定义的自定义协议,加载过程以异步方式执行,使应用在等待数据的过程中保持界面响应,并在数据或错误到达时交付给调用方。[1]
这套接口在苹果平台上有明确的可用范围。同名类的可用版本包括iOS 7.0、iPadOS 7.0、Mac Catalyst 13.1、macOS 10.9、tvOS 9.0、visionOS 1.0与watchOS 2.0;以Objective-C编写时类名为NSURLSession,在Swift中则称为URLSession。[2][3]
它与缓存、Cookie、鉴权、重定向等机制配套工作。请求发出前系统会先查询共享缓存,缓存不可用时再按策略向服务器发起请求,服务器提出的鉴权质询可由共享Cookie或凭据存储自动应答,也可交由委托对象处理,请求还会被已注册的NSURLProtocol对象拦截以改变加载行为。[4]
原理
NSURLSession采用会话与任务分离的结构。会话对象负责协调一组相关的网络数据传输任务,并通过一个会话配置对象定义连接行为,例如对同一主机允许的最大并发连接数、是否允许使用蜂窝网络等;应用可以在一个会话内不断添加任务,每个任务代表对某个具体URL的请求,其间可能需要跟随HTTP重定向。苹果同时提供了不需要配置对象的单例共享会话,适用于需求较简单的场景,但可定制程度低于自行创建的会话。[2]
数据的实际收发由任务完成。所有任务都由会话创建,创建后先处于挂起状态,调用其resume方法才开始执行;会话在请求结束或失败前会保持对任务的强引用,任务本身提供取消、挂起与恢复操作,此外还能查询任务的当前状态、优先级、传输进度以及已发送和已接收的字节数。任务也可以设置专属的委托对象,用来在回调到达会话级委托之前先行拦截。[3]
结果的交付有三种途径:在Swift中使用带async标记的异步方法并以await等待传输完成,或用bytes方法配合for-await-in语法逐块读取;在Swift与Objective-C中提供完成处理块,在传输结束时执行一次;或者实现委托方法,在传输过程中及完成后持续接收回调。无论采用哪种方式,会话实例都会提供状态与进度属性供程序判断当前进展。[2]
协议层面,NSURLSession原生支持data、file、ftp、http与https等URL方案,可按照系统偏好设置透明地使用代理服务器与SOCKS网关,并支持HTTP/1.1、HTTP/2与HTTP/3,其中HTTP/2需要服务器支持应用层协议协商(ALPN)。开发者还可以通过继承NSURLProtocol为应用私有的自定义网络协议和URL方案提供支持。[2]
从iOS 9.0与macOS 10.11起,通过NSURLSession发起的所有HTTP连接都受App Transport Security(ATS)约束,该机制要求连接以TLS协议保护,并要求服务器证书使用至少2048位的RSA密钥或至少256位的椭圆曲线密钥、摘要算法不低于SHA-256、连接的TLS版本不低于1.2、数据以AES-128或AES-256加密,且链路支持完全正向保密。若服务器无法满足要求,应用可以在信息属性列表文件中配置例外来放宽限制。[5][6]
发展历程
NSURLSession的前身是NSURLConnection,后者作为Core Foundation与CFNetwork接口之上的抽象,随2003年Safari浏览器首个发行版本一同诞生,NSURLConnection这个名字实际上指代构成Foundation框架URL加载系统的一组组件,包括NSURLRequest、NSURLResponse、NSURLProtocol、NSURLCache、NSHTTPCookieStorage、NSURLCredentialStorage以及同名类。多年间它支撑了大量Cocoa与Cocoa Touch应用的网络通信,但iPhone与iPad带来的新用例对其若干核心设想提出了挑战,重构随之被提上日程。[7]
2013年的苹果全球开发者大会上,苹果公布了NSURLConnection的接任者NSURLSession,并随iOS 7与OS X 10.9 Mavericks一同提供使用。其接口设计延续了NSURLConnection的铺垫:iOS 5曾为NSURLConnection加入发送异步请求并传入完成处理块的方法,简化了一次性请求的写法,NSURLSession沿用了这一模式,但改为先返回任务对象、允许进一步配置后再启动。[4][8]
新接口带来若干结构性变化:可以为每个会话单独配置缓存、协议、Cookie与证书策略,甚至可以跨应用共享这些信息,从而让框架的网络基础架构与具体应用相互独立;同时任务共享所属会话的公共委托对象,取代了以往每个连接各自持有一个委托的做法;后台会话的加入使应用挂起、退出乃至崩溃时仍能进行上传与下载。[8][7]
此后NSURLConnection逐步退出。到iOS 9,苹果已将NSURLConnection废弃,推荐以NSURLSession承担网络请求相关操作,AFNetworking等第三方框架也从基于NSURLConnection改为基于NSURLSession实现。[9]
该接口并非只存在于苹果的闭源实现中。Swift核心库基金会(swift-corelibs-foundation)在FoundationNetworking模块中提供了URLSession的开源实现,其共享会话使用当前设置的全局缓存、Cookie存储与凭据存储对象;GNUstep也提供了NSURLSession的文档化实现,声明可用版本为MacOS-X 10.9.0。[10][11]
应用
会话按配置分为几种类型。共享会话是不含配置对象的单例,适合需求受限的简单场景;默认会话行为与共享会话相近但可以配置,并允许通过委托渐进获取数据;临时会话不向磁盘写入缓存、Cookie或凭据,同样也不把凭据存入钥匙串,相关信息仅保留在内存中,会话失效即被清除;后台会话则允许应用未运行时在后台完成内容上传与下载。创建会话时可以指定委托,也可以传入nil而不提供委托。[2][12]
任务分为若干类,对应不同的使用场景。数据任务使用内存中的NSData对象收发数据,适合向服务器发出简短且往往具有交互性质的请求,它受默认、临时与共享会话支持,但后台会话不支持。上传任务与数据任务类似,区别在于可以携带请求体以便在上传数据后再取回服务器响应,并支持应用未运行时的后台上传。下载任务把资源直接下载为磁盘上的文件,支持后台下载。WebSocket任务则依据RFC 6455定义的WebSocket协议在TCP与TLS之上交换消息。[3][2]
在Objective-C中,数据任务既可由URL创建(相当于对该URL发起标准GET请求的快捷方式),也可由NSURLRequest创建,后者便于改用POST等请求方法并在请求头中设置授权等信息;上传任务可由请求连同本地的文件或NSData对象创建,下载任务同样需要一个请求,其完成处理块会收到文件在本地的临时位置,需要由调用方把文件移动到永久位置,否则临时文件会被清除。[8][4]
由于这些能力覆盖了移动端常见的网络需求,NSURLSession成为众多第三方网络库的底层基础。AFNetworking 3.0版本移除了所有基于NSURLConnection接口的支持,新的接口完全基于NSURLSession,Alamofire同样是对NSURLSession的封装,SDWebImage则使用NSURLSessionDataTask下载图片。[13][12]
局限
后台会话的适用范围明显窄于普通会话。它要求会话提供用于交付事件的委托方法,只有HTTP与HTTPS协议受支持,并且传输过程中总是伴随重定向;在上传方面仅限于以文件形式上传,上传二进制对象或数据流不受支持。数据任务在后台会话中同样不被支持,在iOS 8与OS X 10.10之前的版本中这一限制更为明显。[12][3]
后台传输的持续性也有边界。用户强制关闭应用时,NSURLSession的连接会被中断;若后台任务尚未全部完成而进程被强制退出,未完成的任务会失败。下载任务被取消后可以生成恢复数据,传给新建的下载任务以继续此前的下载,但这一机制需要调用方显式处理,并非自动完成。[9][4]
会话也有不宜频繁创建的一面。数据、上传与下载任务都需要以会话为容器,若不加复用而每次请求都新建会话,连接复用与HTTP/2多路复用带来的收益就会丧失。此外,App Transport Security只对标准URL加载系统生效,对Network框架、CFNetwork或BSD套接字等更底层的调用不作强制,这些路径的连接安全需由开发者自行保证。[14][5]
会话对象的配置一经创建即不可更改,因为创建会话时复制的是配置对象的副本;配置对象本身可以复制后独立修改,会话与任务对象在复制时返回的仍是同一个对象。[2][15]
参见
-
NSURLConnection —— NSURLSession 的前身,随 2003 年 Safari 首个发行版本诞生的网络请求接口,在 iOS 9 中被废弃。
-
Foundation框架 —— 提供 NSURLSession 及其相关类与协议的苹果系统框架。
-
URL加载系统 —— NSURLSession 所属的整套 URL 资源访问体系。
-
App Transport Security —— iOS 9 起约束 NSURLSession 连接安全性的系统机制。
-
AFNetworking —— 以 NSURLSession 为底层实现的开源网络库。
-
传输层安全性协议 —— NSURLSession 与 ATS 所依赖的加密传输协议。
参考资料
- url-loading-system [引用日期2026-10-14]
- URLSession [引用日期2026-10-14]
- urlsessiontask [引用日期2026-10-14]
- 从 NSURLConnection 到 NSURLSession [引用日期2026-10-14]
- preventing-insecure-network-connections [引用日期2026-10-14]
- NSAppTransportSecurity [引用日期2026-10-14]
- iOS 之NSURLConnection和NSURLSession [引用日期2026-10-14]
- 忘记NSURLConnection,拥抱NSURLSession吧! [引用日期2026-10-14]
- NSURLSession学习 [引用日期2026-10-14]
- URLSession [引用日期2026-10-14]
- NSURLSession documentation [引用日期2026-10-14]
- iOS开发之Alamofire源码解析前奏--NSURLSession全家桶 [引用日期2026-10-14]
- iOS NSURLSession 的相关内容 [引用日期2026-10-14]
- URLSession Caching and Configuration Reference [引用日期2026-10-14]
- NSURLSessionConfiguration [引用日期2026-10-14]