美文网首页
Alamofire源码解析 - Request

Alamofire源码解析 - Request

作者: wanglj | 来源:发表于2017-04-06 15:35 被阅读0次

Request.swift代码结构主要是由Request及其它的三个子类DataRequest,DownloadRequest,UploadRequest组成,另外还有StreamRequest这个类很简单文中就没有提及。

  • Request负责发送请求和接收响应,服务器返回的相关数据,以及管理其URLSessionTas

Request

  • 阅读这段代码注意最重要的私有属性taskDelegate,以及它对应的open属性delegateRequest的操作都是调用对应taskDelegate中的resume(),suspend(),cancel()方法。
    init(session: URLSession, requestTask: RequestTask, error: Error? = nil) {
        self.session = session

        switch requestTask {
        case .data(let originalTask, let task):
            taskDelegate = DataTaskDelegate(task: task)
            self.originalTask = originalTask
        case .download(let originalTask, let task):
            taskDelegate = DownloadTaskDelegate(task: task)
            self.originalTask = originalTask
        case .upload(let originalTask, let task):
            taskDelegate = UploadTaskDelegate(task: task)
            self.originalTask = originalTask
        case .stream(let originalTask, let task):
            taskDelegate = TaskDelegate(task: task)
            self.originalTask = originalTask
        }

        delegate.error = error
        delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() }
    }·

初始化的时候需要传入URLSessionRequestTask,通过不同的requestTask生成不同的TaskDelegate赋值给属性taskDelegate。这么做的原因是子类都是调用这个方法初始化,所以不同的子类传入的requestTask就不同。统一的操作是把originalTask保存了下来,这么做的目的是当请求失败后再次请求时通过originalTasktask方法生成新的URLSessionTask

  • Request的子类都定义了一个实现TaskConvertible协议的类型,用做初始化自己时使用的RequestTask参数、

DataRequest

    struct Requestable: TaskConvertible {
        let urlRequest: URLRequest

        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
            do {
                let urlRequest = try self.urlRequest.adapt(using: adapter)
                return queue.syncResult { session.dataTask(with: urlRequest) }
            } catch {
                throw AdaptError(error: error)
            }
        }
    }

  • 定义TaskConvertible, 通过task()返回URLSessionTask
  • 重写了request属性,在通过父类get方法没有返回值的情况下放回 requestable.urlRequest
  • progress属性用于表示请求进度
  • var dataDelegate: DataTaskDelegate { return delegate as! DataTaskDelegate }把父类的TaskDelegate转化成DataTaskDelegate

DownloadRequest

两种下载方式,createIntermediateDirectories创建中间目录,removePreviousFile删除目的地之前文件

    public struct DownloadOptions: OptionSet {
        /// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol.
        public let rawValue: UInt

        /// A `DownloadOptions` flag that creates intermediate directories for the destination URL if specified.
        public static let createIntermediateDirectories = DownloadOptions(rawValue: 1 << 0)

        /// A `DownloadOptions` flag that removes a previous file from the destination URL if specified.
        public static let removePreviousFile = DownloadOptions(rawValue: 1 << 1)

        /// Creates a `DownloadFileDestinationOptions` instance with the specified raw value.
        ///
        /// - parameter rawValue: The raw bitmask value for the option.
        ///
        /// - returns: A new log level instance.
        public init(rawValue: UInt) {
            self.rawValue = rawValue
        }
    }

两种下载方式,URLRequestData可以继续上次未完成的下载任务。

    enum Downloadable: TaskConvertible {
        case request(URLRequest)
        case resumeData(Data)

        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
            do {
                let task: URLSessionTask

                switch self {
                case let .request(urlRequest):
                    let urlRequest = try urlRequest.adapt(using: adapter)
                    task = queue.syncResult { session.downloadTask(with: urlRequest) }
                case let .resumeData(resumeData):
                    task = queue.syncResult { session.downloadTask(withResumeData: resumeData) }
                }

                return task
            } catch {
                throw AdaptError(error: error)
            }
        }
    }
  • 重写request属性
  • resumeData下载的data

UploadRequest

定义了三种上传的方式

enum Uploadable: TaskConvertible {
        case data(Data, URLRequest)
        case file(URL, URLRequest)
        case stream(InputStream, URLRequest)

        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
            do {
                let task: URLSessionTask

                switch self {
                case let .data(data, urlRequest):
                    let urlRequest = try urlRequest.adapt(using: adapter)
                    task = queue.syncResult { session.uploadTask(with: urlRequest, from: data) }
                case let .file(url, urlRequest):
                    let urlRequest = try urlRequest.adapt(using: adapter)
                    task = queue.syncResult { session.uploadTask(with: urlRequest, fromFile: url) }
                case let .stream(_, urlRequest):
                    let urlRequest = try urlRequest.adapt(using: adapter)
                    task = queue.syncResult { session.uploadTask(withStreamedRequest: urlRequest) }
                }

                return task
            } catch {
                throw AdaptError(error: error)
            }
        }
    }

相关文章

网友评论

      本文标题:Alamofire源码解析 - Request

      本文链接:https://www.haomeiwen.com/subject/prhqattx.html