URLSession Adaptable Connectivity API
当网络请求遇到不可达的情况时,如:
- 无连接上Wifi且无手机信号
- 设备飞行模式
- 只有蜂窝信号,但是allowsCellularAccess为NO
等,会导致请求直接失败。很多APP通常这是时候回监听网络连接状态以待可连接时重新请求或直接重新发起请求。
苹果为了解决这个,在URLSessionConfiguration中增加了waitsForConnectivity属性,当其设置为YES,系统回等到以上几个请求不可达情况消失了才把请求发出去(避免无谓的请求失败)。(此功能在BackgroundURLSession中默认开启)
同时增加了
urlSession(_:taskIsWaitingForConnectivity:)
代理方法通知代理者某个请求等待连接可用
URLSession Scheduling API
主要解决一下三个问题:
- 没必要因为创建NSURLSessionTask而进行额外的后台加载
- 当后台请求创建但还没发出去的时候,这个被创建的请求有可能因为上下文变化的原因导致这个请求无意义
- iOS系统并不知道什么时候去发起你的请求才是最合适的
原先你要做后台数据加载的时候,流程是这样的:
变成
所以当应用在前台的时候,你就可以创建这个NSURLSessionTask,iOS11里面就不会在后台额外launch一次去创建NSURLSessionTask。这就解决了问题1。
iOS11在NSURLSessionTask的delegate里面提供了一个新的方法:urlSession:task:willBeginDelayedRequest:completionHandler:(Backgroud Session 专有)。系统在发起请求之前会调一个这个回调,然后在这个completionHandler里面你告诉系统这个请求是否要发出去,是否要修改。从而解决了问题2。
iOS11也给了NSURLSessionTask一个property:earliestBeginDate。系统在earlistBeginDate之前是不会发起这个请求的。你给这个task设置一个earliestBeginDate,就解决了问题3。
还通过设置NSURLSessionTask的countOfBytesClientExpectsToSend和countOfBytesClientExpectsToReceive来让系统更好地调度你的后台网络任务。
NSURLSession Enhancements
ProgressReporting
以往监听URLSessionTask的进度是通过KVO以下属性来计算进度
countOfBytesExpectedToReceive,countOfBytesReceived,countOfBytesExpectedToSend,countOfBytesSent
但是这样需要做额外的工作
苹果新增了属性
var fractionCompleted:Double
来提供进度
以及属性
localizedDescription,localizedAdditionalDescription:
获取进度的描述
URLSession Brotli Support
URLSession支持Brotli压缩协议
Brotli对比gzip,压缩率提高了15%(HTML,CSS,JS...等)
URLSessionStreamTask
新增了HTTPS认证的流程代理
注: URLSessionStreamTask特性
- 支持TCP/IP直连服务器
- 支持HTTPS
- 完全取代NSInputStream/NSOutputStream
Networking Best Practices
- 不使用BSD Socket
- 不使用embed networking Libaray
- 使用苹果以下的API来获得提升
- Wifi Assist
- Background work
- 使用域名相关API(就是不要直接使用IP)
- 使用timeoutIntervalForResource,timeoutIntervalForRequest设定请求超时时间
- 尽量一个app内共用一个URLSession
- 即使清理动态创建的URLSession,使用finishTasksAndInvalidate和invalidateAndCancel函数
Ongoing Developments
开发TLS1.3中
开发QUIC中
- 全名Quick UDP internet connections
- 由谷歌发起的