SessionDelegate的对外闭包
1. sessionDidReceiveChallengeWithCompletion
2. sessionDidFinishEventsForBackgroundURLSession
3. taskDidComplete
4. downloadTaskDidWriteData
5. dataTaskDidReceiveData
6. dataTaskDidReceiveResponse
7. 等等
SessionManager.default.request(urlStr)
SessionManager.default.delegate.taskDidComplete ={ (session,task,error) in
print("任务完成了")
}
几种事件处理
1.validate
SessionManager.default.request(urlStr)
.response { (response) in
debugPrint(response)
}.validate { (request, response, data) -> Request.ValidationResult in
//处理无数据报错
guard let _ = data else{
return .failure(NSError.init(domain: "xxx", code: 10000, userInfo: nil))
}
//处理常规特征码报错,转成自己定义的错误码,以及提示
let code = response.statusCode
switch code {
case 403:
return .failure(NSError.init(domain: "xxx不通过", code: 10086, userInfo: ["555":"错误"]))
case 404:
return .failure(NSError.init(domain: "xxx不通过", code: 10086, userInfo: ["666":"错误"]))
default:
return .success
}
}
2.RequestAdapter
SessionManager.default.adapter = LwkAdapter()
class LwkAdapter: RequestAdapter {
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
//重定向
//重新请求token
return urlRequest
}
}
3.RequestRetrier
SessionManager.default.retrier = LwkRetrier()
class LwkRetrier: RequestRetrier {
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
completion(true,1) //开始重新请求
completion(false,0) //关闭
//成对使用
}
}
Request详解
- 为上层SesssionManager解耦,SesssionManager对外提供功能request对内管理具体功能实现
- 具体业务功能单独处理,RequestDelegate在SessionManagerDelegate外界相应,功能下发
SessionManagerDelegate与taskDeletage的关系
- DataRequest: Request
- struct Requestable: TaskConvertible 内联结构体
request
- dataRequest
- downRequest
- uploadRequest
- streamRequest
继承request的原因是什么?
根据不同类型的业务实现不同的类
绑定关系
delege[task] = request 做了什么?
- 建立sessionDelegate与task的绑定关系
@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
var originalRequest: URLRequest?
·
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
delegate[task] = request
·
·
}
delegate = sessionDelegate根据[task]读取request ,
- 因为几乎每一个seccionDelegate的回调里边都有task,所以重写下标,根据传进来的task拿到对应功能类型的request
- task与request需要存在依赖关系,但不能相互继承,所以通过
下标法
//下标
open subscript(task: URLSessionTask) -> Request? {
get {
lock.lock() ; defer { lock.unlock() }
return requests[task.taskIdentifier]
}
set {
lock.lock() ; defer { lock.unlock() }
requests[task.taskIdentifier] = newValue
}
}
open func urlSession(
_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL)
{
if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
} else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
}
}
-
delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
做对应的下载完成后的文件操作统一处理 - 为什么要这么做?因为每次request完成后都需要做重复的任务,所以需要下发到最下层的taskDelegate中,再通过sessionDelegate与task的绑定,sessionManager拿到结果,减少sessionManager负担
代理任务下发的两种情况
- 实现了任务代理,由用户自定义处理下载完成后的文件管理,用户处理不了的事件,alamofire处理,比如说队列管理
- 没实现代理,默认存在alamofire指定的路径
taskDelegate里的queue逻辑
- alamofire与afn一样支持通知机制
open func resume() {
guard let task = task else { delegate.queue.isSuspended = false ; return }
if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() }
task.resume()
NotificationCenter.default.post(
name: Notification.Name.Task.DidResume,
object: self,
userInfo: [Notification.Key.Task: task]
)
}
- 可以通过
.startRequestsImmediately = True
来重新开启request -
taskDelegate.swift
中,task初始化的时候指定了队列类型,创建了一个同步的operation - 当前有任务请求队列就挂机,没有任务队列就开始
- 什么时候挂起?queue中有什么
init(task: URLSessionTask?) {
_task = task
self.queue = {
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 1//当前是个同步队列
operationQueue.isSuspended = true//挂起当前队列
operationQueue.qualityOfService = .utility
return operationQueue
}()
}
- 在request开始的时候operationQueue.isSuspended = No开始线程