在开始介绍之前先明确一点,本篇写的不是关于Alamofire是怎么使用的,而是我仔细看了Alamofire框架代码后的一点感受与大家分享。写的不好也请大家见谅。如果是想要学习怎么使用的话还是建议直接阅读github上面的文档Alamofire documentation从基本到高级都讲解的很详细。
Alamofire
对于使用oc的同学来说一定十分熟悉AFNetworking这个框架,因为现在我们的app只要是有关于网络访问的部分大部分都会通过这个框架来进行网络的访问。而本篇要说的Alamofire就是swift版本的AFNetworking拉。所以Alamofire也是进行网络访问的框架。
整体架构
从github上下载Alamofire用Xcode打开可以看到如下的结构目录:
其中主要分为3部分:
- Alamofire.swift文件
- Core核心部分
- Features部分
我主要是分析Core部分的代码,而Features部分的代码我只会分析一部分,因为Features部分的代码是大同小异的只要理解了其中一部分的代码是怎么写的其他的只要在稍稍阅读下就可以了,当然每个部分的代码都有其精彩之处。希望大家有时间也可以自己再去阅读下大家多交流交流😊。
Alamofire.swift分析
在Alamofire.swift文件主要有两个功能:1. 提供了整个框架的入口。2. 向整个框架提供了方便的工具方法。
整个Alamofire.swift文件在内容上面也主要分成了两部分:
第一部分:
在这一部分中主要是定义了两个Convertible协议和一个Convenience方法
两个个Convertible协议代码如下:
这个协议是规定了其他类转化为URLString的方法从而可以使用这个来构造URLRequest。这么做得目的是将个各类的转化方法和方式分散到个各类中各自实现,就可以避免出现一大坨的转化方法,实现代码的美观。同理在接下来的URLRequestConvertible也是这个道理
接下来就是工具方法了
这个方法是用来构造NSURLRequest的简便方法,其中有一个参数就是URLStringConvitible类型的。所以如果我们自己的某个类也实现了URLStringConvertible协议也是可以通过这个方法构造NSURLRequest的。在有一个Method类型这个类型是
定义在ParameterEncoding.swift文件中。
接下来就是提供了整个框架的入口方法,这里就先不做介绍等下面的Core部分懂了那么这部分就很自然的懂了
Core部分
在正式介绍整个核心部分之前,必须要有NSURLSession的基础知识,因为整个Alamofire框架其实是对NSURLSession进行封装的。如果对这一方面的只是缺乏还是建议先去补充一下,不然的话你会不知道接下来为什么要这么做。
在3个文件中总共是有Manager类、Request类和ParameterEncoding枚举类型。
Manager类:封装了NSURLSession以及相对应的代理方法
Request类: 封装了NSURLSessionTask以及Task的基本的代理方法
ParameterEncodeing:负责对HTTP请求的参数进行编码
框架总体流程是:
这个是发送的流程,我们调用Alamofire.swift里的方法,而Alamofire里的方法其实是创建一个Manager调用Manager里的方法将得到的NSURLSessionTask封装成Request实例,发送并且返回Request实例。
在消息发送成功了,服务器处理好以后,需要将处理好的回复发送回来那么在发送回来的时候首先是调用了Manager的代理方法,然后在Manager中调用Request类的方法,最后才是掉用response方法和progress方法等。
那么在我们进行网络访问的时候一定不是只是发一个Request这么简单,而是有很多个Request那么在有回调的时候Manager是怎么知道是哪个Request的回调呢?那么接下来这就要求我们知道Manager里面是如果工作的。
Manager
先上Manager的图
属性:
session: NSURLSession类型发送请求并且得到NSURLSessionTask
delegate: session的代理
queue:实现session线程安全的队列
startRequestsImmediately:是否立刻发送请求
backgroundCompletionHandler:后台运行完成后的回调的closure
现在我们看以下Manager的request方法
在两个request方法中其中一request方法是先将参数封装成NSURLRequest在调用另一个重载的request方法,并且在封装成URLRequest的时候还对参数进行了编码。
我们的重点是在request(URLRequest:)这个方法这里。这个方法里面先是得到一个NSURLSessionTask然后将Task封装成Request,并将Request的delegate 存入自己的delegate的里面然后放回。
到这里为止Manager在将URLRequest封装成Request的时候就已经将Request的delegate存放到自己的delegate里面,好在后面的时候可以使用。
接下来就是Manage类里面的重头戏,session的代理。
先看SessionDelegate类的属性部分,但在此之前先跟大家提一下这个类是Manager的内部类,而且它的修饰符是final,这就意味着这个类是不可被继承的。那为什么是内部类呢?这里就留给大家好好体会😊
在SessionDelegate类里面有字典subdelegates这个就是在request里面用来存放request的delegate的。而下面的subdelegateQueue则是保证对字典的线程安全。在这里我们还注意到SessionDelegate还实现了subscript下标主要是为了存取方便,也顺便吧线程安全的操作一起写入。
同时,我们也可以注意到SessionDelegate实现了所有NSURLSession应该实现的所有协议NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDataDelegate和NSURLSessionDownloadDelegate。那么接下来我们看他是怎么实现的
因为太长了所以我只截取了NSURLSessionDelegate部分。大家可以注意到在这里主要有两大块一块是Override Closures部分,另一块是DelegateMethod部分,而且这两块是相互对应的。那么为什么这么做呢?因为可以让使用者对其中一些方法进行自定义同时也建议大家看看这篇文章更轻量的 View Controllers。每一部分Delegate都是以这种形式写的。所以Alamofire给使用者提供了很大的自定义的空间。
Request
同样的Request类在处理上面也是有内部来处理代理的主要结构入下图所示:
在Request里面有两个代理,分别是TaskDelegate和DataTaskDelegate。同样都是内部类,那么为什么要这么分呢?那是因为NSURLSessionTask是有不同的类型的:
NSURLSessionUploadTask:上传任务类型
NSURLSessionDataTask:请求数据类型
NSURLSessionDownloadTask:下载类任务
而我们平常的GET、POST请求就是属于DataTask类型的。而每种类型的Task都有需要实现的协议UploadTask和DataTake所需要实现的协议是
NSURLSessionDataDelegate而DownloadTask所需要实现的协议是NSURLSessionDownloadDelegate。而不管是哪一种类型的Task都需要实现NSURLSessionTaskDelegate。所以在Request的内部类中TaskDelegate是实现了NSURLSessionTaskDelegate,DataTaskDelegate在继承了TaskDelegate的基础上实现了NSURLSessionDataDelegate。那么Download类型的呢?因为Download在一般的app中比Data出现的概率小,所以不应该出现在核心部分,所以Download是以扩展的形式在Features中Download.swift文件中实现的。
所以Request类的核心部分最主要的就是基础的TaskDelegate类是怎么实现的:
在TaskDelegate中我们最主要的是关注两个属性一个是task属性和queue属性。task 属性就是NSURLSessionTask类型,所以在这里我们知道Request吧基础Task封装到Delegate里面而外层的Request只是一个提供方便方法的外套而已。另外一个需要关注的属性queue是一个队列。而且大家注意到在队列初始化的时候吧队列的suspended属性设置为true,说明不希望队列里面的任务立刻执行。那么什么时候执行呢?我们直接跳到Delegate的代理方法
在代理方法didCompleteWithError的时候将queue的suspended属性设置成false就是说明现在立刻运行。所到这里的时候我们就已经可以知道这个queue是存放这Request完成请求以后需要完成的东西。那么这个是什么东西呢?
这个东西就是我们在使用Alamofire的时候所调用的.progress方法和response方法等等。在调用这两个方法的时候会将我们需要执行的代码打包成closure存入queue中等拿到了服务器的回复后在让queue运行存放在里面的closure。
所以到这里为止本篇文章的目的已经达到了。因为篇幅有限不可能面面俱到,只能向大家解释基本的流程。至于Features里面的内容大部分是Manager和Request的扩展。建议大家如果感兴趣的话,还是阅读源码比较好。
如果大家有什么不明白的可以问我,文章写的不好勿喷。