iOS开发之Alamofire源码解析

今天博客中的Alamofire源码的版本是以3.4版本为例。上篇博客系统的对NSURLSession相关的东西进行了详细的解析,详情请看《详解NSURLSession》,为了就是给本篇博客打下基础。由于AlamoFire就是对NSURLSession及其相关的东西进行了进一步的封装,让网络请求使用起来更为简单。本篇博客就详细的来窥探一下AlamoFire源码,主要来看一下AlamoFire是如何对NSURLSession进行封装的,而且来看一下在封装时使用了哪些Swift语言中的高级用法,也就是看一下Swift语言进一步的使用方法。html

固然AlamoFire是AF的Swift版本了,其中虽然是使用Swift语言实现的,可是实现思路与AFNetWorking大同小异。若是你以前阅读过AFNetWorking的源码,那么你对Alamofire的源码应该并不陌生,好多地方的实现思路是一致的。今天博客中不是教你如何去使用AlamoFire,而是告诉你Alamofire是如何实现的。本篇博客中的干货仍是比较足的,关于AlamoFire的官方文档请移步Alamofire -- github连接git

下方第一部分的类图是在阅读AlamoFire源码时为了梳理每一个结构间的关系画的一个简单的类图,下方的类图没有涵盖AlamoFire中全部的类,而是给出了核心部分的模块以及各个模块间的关系。接下来咱们将对下方的模块进行拆分,而后各个击破。本篇博客的主题思路是先总体的看一下AlamoFire的组织架构,并解析每部分的关系。而后对每一个模块进行详细的解析,在解析时咱们会对一些Swift语言的知识点进行提取,而后将其进行剖析。github

 

一.Alamofire核心模块概述

咱们先总体上来看一下AlamoFire这个框架关系,概述一些核心模块。该部分咱们先来看一下AlamoFire的文件组织结构,而后在给出这些文件组织结构中类的关系。因此在本部分类图是少不了的。废话少说,进入该部分的主题。编程

1.Alamofire的目录结构解析

首先咱们来看一下AlamoFire的目录结构,从总体上来把控一下AlamoFire。下方截图是AlamoFire框架的全部文件,文件不算多,Alamofire框架的源代码并不算多,全部理清Alamofire的框架结构仍是不难的。下方截图中是AlamoFire中的全部文件,Core文件夹下是Alamofire的核心文件,Features主要是对核心文件的扩展。今天咱们就以核心文件为主,Feature文件为辅来窥探一下AlamoFire框架的源码。swift

下方是对Core文件夹下的各个文件的功能简述:设计模式

  • Alamofire.swift ---- 该文件中主要是给用户提供一些便利的调用方法,用户能够直接调用该文件中的便利方法来使用Alamofire相关功能。
  • Manager.swift ---- Manager中定义了Session对象,Session相关的Delegate,以及Delegate执行的队列等相关信息,在Manager中建立Request对象发起请求。Manager管理的就是各类请求,Manager对象是以单例的形式对外开放的。
  • Request.swift ---- 该文件如其名,就是负责建立Session的各类task的,并执行相关的SessionTask,并调用相关书籍解析的功能模块对数据进行解析并经过回调返回给用户。
  • ParameterEncoding.swift ---- 负责请求参数的各类编码( URL、URLEncodedInURL、JSON、PropertyList等编码),并将编码后的数据与URLRequest结合后的结果进行返回。
  • Result.swift ---- 对解析后的数据封装成Result对象。
  • Response.swift ---- 负责将服务器相应的数据进行封装生成Response对象,该对象中就包括上述的Result对象,用户最终会经过闭包回调的形式获取到该Response的对象。
  • Notifications.swift ---- 其中是一个Notification结构体,该结构体中定义了一些字符串,这些字符串就是所需通知的Key,当网络请求DidResume、DidSuspend、DidCancel、DidComplete都会发出通知。
  • Error.swift ---- 其中是一个Error的结构体,其中封装的是各类错误状态。

Features文件夹下各个文件的功能简述:服务器

  • Download.swift ----- 对Manager和Request类进行扩展,使其支持Down Task,其中封装了 NSURLSessionDownloadDelegate相关代理方法。
  • Upload.swift ---- 在该文件中也是对Manager和Request类进行的扩展,使其支持Upload Task,其中封装了 NSURLSessionDataDelegate中获取上传数据进度的代理方法,也就是 taskDidSendBodyData代理方法。
  • MultipartFormData.swift ---- 该文件从名字就能够看出是为了组织多表单数据上传的数据的,在Upload Task中就使用到了 MultipartFormData
  • Stream.swift ---- 和Download和Upload文件类似,该文件中也是对ManagerRquest作延展,主要使其支持数据流的传输,其中主要封装和实现了 NSURLSessionStreamDelegate相关的代理方法。
  • ResponseSerialization.swift ---- 该文件中主要是对Request类进行数据解析的延展的。其中封装了各类对响应数据的解析方式,其中包括Data、String、JSON、PropertyList 等解析方式。
  • NetworkReachabilityManager.swift ---- 该文件主要是对 SystemConfiguration .framework中的 SCNetworkReachability 相关的东西进行封装的,主要用来管理和监听网络状态的变化
  • ServerTrustPolicy.swift ---- 这个文件主要是对NSURLSession作的延展,其中定义了各类网络请求的认证策略,主要证书认证相关东西。
  • Timeline.swift ---- 该文件是为了方便调试而生的,其中记录了相关操做的时间点,而且对其进行记录,便于在Debug时使用到。
  • Validation.swift ---- 主要是用来验证请求是否成功,若是出错了就作相应的处理。

上面是AlamoFire中全部文件的概述,上面这些算是对AlamoFire框架有大概的了解吧。结合上方的概述,来研读AlamoFire源码仍是比较清晰的。下方就是AlamoFire 3.4中相关文件的木头结构,以下所示:网络

  

 

2.核心类间的结构

上面简单的介绍了Alamofire框架的目录结构以及每一个文件所负责的内容。接下来咱们进入到各个文件的内部,来总体的看一下核心类之间的关系。下方是核心类的“类图”,固然下方只是核心类的。接下来来概述一下下方的类图,由于下图太大,在此看起来不太清楚,若是你感兴趣,你能够另存为,而后放大查看。session

  • 下方黑框中的部分对应的就是Alamofire.swift中的内容。其中主要是一些URL转换字符串的延展以及 URLRequst转换成 MutableURLRequest的延展,还有一些用户使用的便利方法。
  • 黄框中就是咱们 Manager.swift中的内容了, Manager类的对象是以单例的形式对外展示的,上述黑框中的便利方法,主要是获取Manager类的单例,而后调用相应的方法。
  • 绿框中所对应的主要是 Request.Swift和Features文件夹中的内容,主要是Request类及其延展,固然还有对 ManagerNSURLSession的延展。
  • 红框中的就是网络请求会话的各类任务的回调方法的封装了,在这些回调方法中提供了默认实现,并对外留有回调块,以便让用户来本身实现这些回调方法。

  

 

2、Alamofire.swift源码解析

第一部分算是概览了一下Alamofire框架中的各个组成部分,接下来该进入到上述的各个模块中来进一步来窥探其实现和组织方式了。仍是“顺藤摸瓜”,先从用户看的到的地方着手,而后层层深刻,直到你看不见的地方。因此第二部分咱们先来看一下Alamofire.swift中的内容,由于该文件是Alamofire框架的入口。闭包

1.Alamofire.swft中的类图结构

下方的类图就是第一部分类图中黑框的放大版,根据Alamofire.swift这个文件咱们不难画出下方这个类图。有一点要说明的就是在类图中省略了一些遍历方法,只写了一些主要的,不过核心的功能仍是有的。下方的URLStringConvertibleURLRequestConvertible是负责类型转换的接口,具体的请看下方的介绍。该文件中除了类型转换的方法外就是一些调用Manager的单例的便利方法了。

  

2.Alamofire.swift技术细节

下方就是URLStringConvertible协议以及相关延展的具体实现,主要功能就是将String、NSURL、NSURLComponents、NSURLRequest中的URL转换成字符串类型。将要转换的类型要遵循URLStringConvertible协议,并在计算变量URLString中返回转换后的字符串。具体作法以下所示,这中类型转换方式在开发中常常会使用到,下方会给出其余实例。URLRequestConvertible协议的功能与URLStringConvertible大同小异,URLRequestConvertible协议的实现者负责将NSURLRequest转换成NSMutableURLRequest类型。在此就不作过多的赘述了。

  

下方截图是Alamofire.swift中的一个便利方法,其余几个便利方法与此类似,都是调用Manager单例中相应的方法,便利方法为了链式调用Request类中的相关方法,因此全部的便利方法都会返回当前Manager单例使用的Request对象。具体以下所示:

  

 

3.扩展用例

学以至用,触类旁通。上面那种“面向协议”开发的思想值得咱们学习,以前在设计模式相关的系列博客中不止一次的提到过要“面向接口编程”,此处的协议就是接口。虽然上面只是使用协议来进行简单的类型转换,这种思想是很是值得咱们学习的。经过上面类型转换的方式,咱们能够写出下方代码。下方代码不是Alamofire框架中的代码,是我根据上述的类型转换的实例所实现的,下方定义了一个类型转换的协议,须要转换的类型要遵循这个协议,下方以String为例,具体作法以下所示。

  

 

3、Manager.swift源码解析

由于便利方法主要是调用的Manager类的单例,因此接下来咱们来看Manager.swift中的东西。Manager类中主要负责SessionRequest的初始化,而且提供SessionDelegate代理方法的默认实现。在实现代理方法时留出了相应的闭包已提供给用户使用该闭包来回调相应的代理方法。在Manager中的SessionDelegate类就是NSURLSessionDelegate以及相关子协议的代理类 ,其中就给出了各个代理方法的默认实现,在实现时并定义了一系列的Closure回调变量,当这些闭包变量不为空时就会执行闭包块中的内容,而不会执行提供的默认实现。

1.Manager.swift相关类图

下方类图就是黄色部分的放大版,主要是Manager类与SessionDelegate的关系。从下方类图中不难看出,SessionDelegate类遵循了NSURLSessionDelegate协议以及子协议,并给出了代理相应的实现方法。下方的代码会给出代理的具体封装和实现方式。

  

 

2.Manager类的相关属性

开门见山,由于Manager类对外是以单例的形式对外使用的,因此咱们先来看看Manager类的单例实现。下方截图中的sharedInstance计算属性就是Manager的单例,其中存储的就是一个Manager对象,在建立Manager对象时咱们为Manager对象中存储的NSURLSession对象指定了一个defaultSessionConfiguration和一个defaultHTTPHeaders。

  

上面是Manager类中单例的实现,接下来咱们来解析类中核心的属性,下方是一些核心属性的解析:

  • defaultHTTPHeaders属性 : defaultHTTPHeaders是Manager类中的一个计算属性,负责组织默认的请求Header中的内容。
  • session属性: 该属性的类型是NSURLSession类型的,负责请求会话,并建立各类会话任务。
  • queue属性:该属性是一个串行队列,该队列负责执行session建立Session Task的任务。
  • delegate属性:该属性是SessionDelegate类型的,而SessionDelegate类遵循了NSURLSessionDelegate及其子协议,并给出了相应的实现,在下方会着重介绍SessionDelegate。而此处的delegate属性负责调用SessionDelegate类中相应的回调方法。

 

3.Manager类的request方法

在Manager.swift源文件中给出了request方法的实现,Manager类的单例所调用的upload、download等方法是在其余源文件中作的延展。那些延展中的方法稍后在聊,本部分中就先对request方法进行解析。下方的方法就是咱们在便利方法中使用Manager类的单例所调用的方法。method参数表示请求方式(GET, POST, PUT等),URLString参数是请求地址,parameter就是请求参数了。encoding参数就是请求参数的编码方式,此处默认是URL编码。headers字典参数就是请求头信息了,默认为nil。下方代码主要是建立NSMutableURLRequest对象,而后将参数进行相应的编码后添加进NSMutableURLRequest对象中,而后调用request()方法发起请求。

  

下方代码段是上述函数中所调用的request()方法,下方的request()方法负责经过Session建立dataTask,也就是负责执行Data Task任务。而后在初始化Request类的对象时,将建立的Data Task对象传给Request对象。而后将Request对象的 Task Delegate对象存入Manager类的delegate属性中。由于在delegate属性中的代理方法是调用相应的Task Delegate的方法,因此在此有必要进行存储。而后调用Request对象的resume()方法发起数据的网络请求。为了链式调用Request对象的其余方法,因此将Request类的对象进行返回。代码以下所示:

  

 

4. Manager中SessionDelegate解析

SessionDelegate能够说是代理的代理,由于在SessionDelegate中有一个subdelegates字典属性,该属性负责存储Request对象中的各个Task Delegate。而SessionDelegate在相应的代理方法中会经过存储的Task Delegate来调用Task Delegate中的方法,因此SessionDelegate说是代理的代理。

下方代码段是SessionDelegate类中部分代码的截图,其中的subdelegates字典属性中存储的就是Request中的TaskDelegate,subdelegateQueue是一个并行队列用来同步执行获取和设置字典中的Task Delegate对象。而后就是为SessionDelegate类定义了一个下标,该下标的功能是以Session Task为下标的形式向subdelegates中添加和获取相应的Task Delegate。该自定义下标就可让类的对象使用下标的形式来设置和获取属性的值,稍后会给出扩展的Demo。

  

关于SessionDelegate中所实现的代理方法,在此咱们就一执行Data Task请求的didReceiveData代理方法为例。下方截图就是SessionDelegate中的didReceiveData代理方法。代码比较简单,首先判断该代理方法对象的Closure回调变量是否有值,若是有就执行该闭包回调块,若是没有值就获取咱们存储的Data Task Delegate, 而后去执行Data Task Delegate中的didReciveData方法。其余方法也于此相似,因此就以点代面,在此就不作过多的赘述了。

 

5.知识点扩展

接下来有到了触类旁通,扩展知识点的时刻了。接下来咱们单独来建立一个小实例来看一下Swift中自定义下标是怎么回事。大道至简,接下来咱们将上述下标的使用进行简化,建立一个Demo, 而后经过这个Demo来介绍一下下标的使用。

下方代码段就是咱们建立的简化版的下标示例,在Swift的类中是支持自定义下标的,自定下标可让你如下标的形式来访问和设置属性。下方就自定义了一个下标,在下标中设置和返回value属性的值。用法以下所示:

  

 

4、Request.swift源码解析

逐渐深刻,咱们如今来到了Request.swift这个类,由于上面的Manager中的请求最终走到了Request类的位置,因此接下来咱们要分析的就是Request.swift源文件中的内容。Request.swift源文件中主要是执行的Data Task请求,而且实现了相应的Data Task Delegate中的方法。其余的任务例如Download Task, Upload Task,Stream Task等会在其余文件中对Request作延展时执行上述这些任务。咱们在此就以Data Task为例。Request类中说白了就是负责经过会话建立相应的Task,并实现相应Task的代理方法。

1. Request相关类图

下方类图就是Request相关类图了,Request类及其延展中就是建立各类类型的Task,而后给出相应的Task Delegate。下方类图还给出个各类Task Delegate间的继承关系。Request相关源文件在给出TaskDelegate的代理方法的实现时,也封装了闭包状态下的回调方法。这中作法与SessionDelegate中作法一致。下方会给出具体的介绍。

  

 

2.Request类的初始化方法

下方就是Request类的初始化方法,方法须要两个参数,第一个参数是NSURLSession的对象,该对象也就是Manager单例中建立的Session的对象。而第二个参数虽然是Manager传过来的,可是初始化task的任务还得交给Request类来作,Manager来只不过是定义了一个NSURLSessionTask的类型传到了Request中,例如在Manager的request()方法中task是NSURLSessionDataTask,Manager的upload()方法中的task是NSURLSessionUploadTask类型。

在Request的初始化方法中根据Manager单例提供的task的类型来肯定是建立DataTaskDelegate、UploadTaskDelegate等。在相应的Task Delegate中会建立相应的Task。咱们还以上述的DataTask为例,若是你调用Manager单例中的request()方法就会执行下方的DataTaskDelegate()的初始化。以下所示:

  

上面的delegate是TaskDelegate类型的,由于UploadTaskDelegate、DownloadTaskDelegate以及DataTaskDelegate都是TaskDelegate的子类,因此此处用到了面向对象的“多态性”。下方两个属性就是Request类中的delegate和task属性,delegate的初始化在上述Requset的初始化方法中,而此处的task是一个存储属性,task的初始化是放在相应的TaskDelegate中的,在TaskDelegate中建立完task对象后再赋值给Request类中的task属性,以下所示:

  

 

3. Requset类中的Progress闭包

在使用Request类的对象时,咱们能够链式的调用Request中的方法,最经常使用的就是获取相应任务执行的进度,也就是平时我使用的progress()方法。下方截图中的代码段就是progress()方法的实现。经过Task Delegate的类型来判断目前执行的哪一种任务,而后将传过来的progress的闭包赋值给相应的Task Delegate,在这些Task的Delegate中会在相应的回调方法中获取任务执行进度,而后执行下方传入的Closure

  

 

4.Request的resume()方法

下方就是Request类中的resume()方法,其中的代码比较简单。主要是用来记录startTime,而后调用task的resume方法开始执行任务。固然在开始执行任务后要发起相应的通知,此处发出的是DidResume通知。全部的通知类型都在Notifications.swift文件中的Notifications结构体中存储着。Request类中的其余方法,好比suspend()、cancel()方法的实现方式与resume()相似,而且都会发出相应的通知,在此就不作过多的赘述了。

   

 

5.Request类中的相关代理类

从第一部分中的类图中咱们能看出与Request类相关的代理类,TaskDelegate是全部代理类的基类。在该代理类中其实就是定义了一下必要的属性和NSURLSessionTaskDelegate中对应的回调方法,而且为这些回调方法提供相应的闭包回调的形式。此处就以TaskDelegate代理类为例。下方就是TaskDelegate代理类为NSURLSessionTaskDelegate中相应的代理方法提供的Closure方式。其余的代理类如DataTaskDelegate、DownloadTaskDelegate等与此相似。而相应的代理方法中就是对回调进行了处理,不过在处理以前会判断相应的Closure是否为nil, 若是不为nil的话就执行Closure闭包块中的内容。若是为nil,就执行提供的默认处理。

  

 

事无巨细,至此Alamofire中的核心类就已经介绍完毕,由于篇幅有限,其余类在此就不作过多赘述了。其余类以及其余文件中的内容在第一部分中作了概述,其内部的实现细节就不作过多赘述了,在Github上分享的代码对这些类的关键技术细节给出了注释。

在Alamofire框架中大量的使用了延展、闭包以及枚举关联值。特别是在解析网络请求的数据时,将闭包类型做为函数的参数,而后经过闭包变量来提供相应的解析方案,在此就不作过多的赘述了,其余技术细节“仁者见仁,智者见智”。听我说再多,看再多的技术博客若是不亲自的去了解一下,说再多也是没用的,实践出真知。关于Alamofire源码的其余内容在此就不作过多赘述了,若是感兴趣就亲自的去阅读吧,欢迎互相交流。今天博客就先到这儿。

github分享连接:https://github.com/lizelu/iOS_NetWorkingAndAlamofire

相关文章
相关标签/搜索