Alamofire的设计之道

前言:

Alamofire是一个由Swift编写的优雅的网络开发框架。

大部分用Swift编写的iOS App的网络模块都是基于Alamofire的。作为Swift社区最活跃的几个项目之一,有许多开发者在不断的对其进行完善,所以学习这种优秀的开源代码对深入理解Swift的特性很有帮助。

本文很长,大到整个框架的设计,小到某些基础功能的使用都会涉及。


URL Loading System

iOS的网络开发(URL Loading System)的类层次如下:

从图中可以看出,整个框架包括URL Loading相关的核心类和五种辅助类。其中,五种辅助类划分如下

  • Configuration 配置信息,比如Cookie的存储策略,TLS版本等等。
  • Authentication and Credentials 授权和证书
  • Protocol support 用做proxy来拦截或特殊处理某些URL
  • Cookie Storage 管理Cookie
  • Cache Management 管理缓存

Alamofire就是建立在NSURLSession上的封装。

NSURLSession是在2013年推出的新API,并且Apple在2015年废弃了NSURLConnection。如果你的App还在用以NSURLConnection建立的网络层(比如AFNetworking 2.x),那么你真的应该考虑升级到NSURLSession(比如AFNetworking 3.x),废弃的API也许还能正常工作,但是Apple已对其不再维护,当然也就不支持HTTP 2.0等新特性。

关于NSURLSesson的基础使用,我之前有过几篇博客,可以在这个链接找到:

那么,用NSURLSession来进行HTTP/HTTPS请求的时候,实际的过程如何呢?

  • 建立NSURLSessionTask,并且resume.
  • 检查cache策略,如果有需要从本地cache中直接返回数据
  • 通过DNS进行域名查找
  • 建立TCP连接
  • 如果是HTTPS,进行TLS握手(如有资源需要认证访问,可能需要客户端提供证书,用户名密码等信息)
  • 请求开始,收到HTTP的Response
  • 接收HTTP的Data

Tips: 理解HTTP/HTTPS的请求过程很重要,因为往往你需要统计API请求在哪个阶段出了问题,然后对症下药,提高用户体验。


整体架构

Alamofie的整体功能图如下:

其中

  • 左侧是暴露给外部的接口,右侧是内部实现相关
  • 这三个模块比较独立:AlamofireImageAlamofireNetworkActivityIndicator 是基于Alamofire开发的独立的库,分别用来做图片和网络状态小菊花,NetworkReachabilityManager也是先对独立的用来检测蜂窝移动,WIFI等网络变化的。

我们先从一个API调用切入,来分析各个模块的作用:

Alamofire.request(/**/).validate(/**/).responseJSON {
  /**/}
初始化SessionManager的单例default
//整理后代码
self.delegate = SessionDelegate()
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)

在初始化SessionManager代码里,提供了一个默认的SessionDelegate,并且初始化了一个URLSession,这个URLSession的delegate是SessionDelegate。

通过这个初始化,我们知道URLSession的几个代理事件都是传递给SessionManager的SessionDelegate了。

执行全局方法Alamofire.request

方法体中调用SessionManager.default单例的实例方法来创建DataRequest。这一步做了如下动作:

  • 根据传入的url,parameters等参数创建URLRequest
  • 根据URLRequestSessionManager的属性session(URLSession),adapter(请求适配器),queue(GCD queue)创建URLSessionDataTask
  • 根据基类Request提供的方法,创建子类DataRequest实例,并且为子类DataRequest初始化一个DataTaskDelegate

每一个DataRequest对应一个DataTaskDelegate,每一个TaskDelegate有一个OperationQueue,这个queue在初始化的时候是挂起状态的,并且是一个串行队列(maxConcurrentOperationCount = 1)。

open class Request{
    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
        //省略
    }
    delegate.error = error
    delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() } //加入统计请求结束的Operation
    }
}
  • 按需执行DataTask的resume方法
执行DataTask.validate

内容很简单,就是把传入的闭包保存起来,等待后续执行,并且返回Self

执行DataTask.responseJSON

在这个方法里,创建一个NSOperation加入到DataTaskDelegate的queue中,这个queue在创建之初是刮挂起状态的,所以提交的任务不会执行

URLSession收到数据

首先SessionDelegate代理方法被调用:

open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
    if let dataTaskDidReceiveData = dataTaskDidReceiveData {
  //有自定义实现
            dataTaskDidReceiveData(session, dataTask, data)
        } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate {
  //走默认实现
            delegate.urlSession(session, dataTask: dataTask, didReceive: data)
        }
}

在这个代

  • 10
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值