Alamofire源码学习

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Alamofire源码学习相关的知识,希望对你有一定的参考价值。

Core文件夹:
         Alamofire.swift - - - 该文件中主要是给用户提供一些便利的调用方法,用户可以直接调用该文件中的便利方法来使用Alamofire相关功能。
         Manager.swift - - - Manager中定义了Session对象,Session相关的Delegate,以及Delegate执行的队列等相关信息,在Manager中创建Request对象发起请求。Manager管理的就是各种请求,Manager对象是以单例的形式对外开放的。
         Request.swift - - - 该文件如其名,就是负责创建Session的各种task的,并执行相关的SessionTask,并调用相关书籍解析的功能模块对数据进行解析并通过回调返回给用户。
         ParameterEncoding.swift - - - 负责请求参数的各种编码(URL、URLEncodeInURL、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类进行扩展,使其支持Download Task,其中封装了NSURLSessionDownloadDelegate相关代理方法。
         Upload.swift - - - 在该文件中格式对Manager和Request类进行的扩展,使其支持Upload Task,其中封装了NSURLSessionDataDelegate中获取上传数据进度的代理方法,也就是taskDidSendBodyData代理方法。
         MultipartFormData.swift - - - 该文件从名字就可以看出是为了组织多表单数据上传的数据的,在Upload task中就使用到了MultipartFormData。
         Stream.swift - - - 和Download和Upload文件相似,该文件中也是对Manager和Request做延展,主要使其支持数据流的传输,其中主要封装和实现了NSURLSessionStreamDelegate相关的代理方法。
         ResponseSerialization.swift - - - 该文件中主要是对Request类进行数据解析的延展的。其中封装了各种对响应数据的解析方式,其中包括Data、String、JSON、PropertyList等解析方式。
         NetworkReachabilityManager.swift - - - 该文件主要是对SystemConfiguration.framework中的SCNetworkReachability相关的东西进行封装,主要用来管理和监听网络状态的变化。
         ServerTrustPolicy.swift - - - 这个文件主要是对NSURLSession做的延展,其中定义了各种网络请求的认证策略,主要证书认证相关东西。
         Tileline.swift - - - 该文件主要为了方便调试而生,其中记录了相关操作的时间点,并且对其进行记录,便于在Debug时使用到。
         Validation.swift - - - 主要是用来验证请求是否成功,如果出错了就做相应的处理。
 
 
 
 
 
 
2、我的理解:Alamofire在实现中的特点;
(1)、根据URL生成task是使用dispatch_sync进行(防止多线程问题,task的生成在一个线程内);
         dispatch_sync(queue) {
               dataTask = self.session.dataTaskWithRequest(URLRequest.URLRequest)
         }
 
(2)、TaskDelegate的定义在Request类中,以类中类的方式存在,且只继承于NSObject;
 
 
(3)、SessionDelegate扩展了下标方法,下标方法中,取使用同步的dispatch取,存则使用dispatch_barrier_async去存,barrier的task会在这个concurrent的queue中的所有在自己之前开始执行的任务执行完成后再开始,同样在自己之后提交到这个concurrent的queue中的任务也会在自己执行完成之后开始执行;这样做很好的避免了资源竞争引起的数据不同步;
        同时,SessionDelegate中设置了 subdelegates 的 [Int : Request.TaskDelegate] 键值对来分发delegate的回调处理;下标方法操作的就是 subdelegate ,而且在get方法中,根据参数的task的taskIdentifier来取得对应的delegate,且获取的步骤使用了sync的同步操作;??????????,不太明白为什么;而在set方法中,是使用了barrier 的方法来赋值新值;使用的依然是全局的subdelegateQueue,set里面之所以使用 barrier 可能是因为这个队列是全局使用的,为了防止我再存入新的值的时候会有调用;但是一个task对应一个taskIdentifier应该也不会重复的吧;???????
 
 
(4)、具体请求的响应;
                  DataTaskDelegate、DownloadTaskDelegate、UploadTaskDelegate都是继承于TaskDelegate,而在TaskDelegate中有一个 NSOperationQueue 类型的属性 queue ,因为继承关系,这三个delegate中也是有这个变量的;同样在TaskDelegate的初始化中,也初始化了这个queue;且初始的suspended为true,maxConcurrentOperationCount为1;初始化部分使用了匿名方法的方式进行;对应的,在deist方法中调用了queue的cancelAllOperations方法和suspended设为了false;且当接收到数据后才会被置为false,此时它内部添加的operation即response的解析化才回真正执行,解析后执行回调completionHandler
                   也就是说其实请求成功执行的回调其实封装在了一个在=operation上,而一个delegate有一个queue,一个queue中只有一个operation,而queue在创建的时候开始都是暂停的,直到收到数据,这一个请求的代理方法回去开启自己对应的queue,而因为queue已经开启,之前添加的operation开始执行;
                   这里也有另外一点,DataTaskDelegate、DownloadTaskDelegate、UploadTaskDelegate三个delegate,虽然是名字中有delegate,但并不是单纯的protocol,而是声明为了class ,但是其中实现了NSURLSessionDataDelegate、NSURLSessionDownloadDelegate协议方法;其中UploadTaskDelegate继承于DataTaskDelegate 
 
 
(5)、一个请求发生的方法调用;
                   调用request(...)公共方法1  ->  1中调用了 Manager.shareInstance.request(…) 2 ->  2中调用了该单例中的另一 request(…) 方法3  ->  3中调用了 Request(…) 方法4,创建一个Request对象  ->  4中调用了 DataTaskDelegate(…) 方法5来初始化一个TaskDelegate的子类,而在创建这个子类时,也就有了类型为NSOperationQueue的变量queue(初始为暂停),同时也添加了一个operation  ->  因为5其实是带有代理回调的,所以请求结束后,会触发系统session的毁掉方法,再进行传递;
                  这样的处理方式,其实是一个请求一个Request对象,Request对象中包含一个delegate对象,也就对应了一个queue,因为queue只维护一个operation,而一个请求的发起和回调都是在一个operation上面进行,从而保证数据请求不会错乱,不会是A请求的结果却回调了B请求的回调的执行;还因为A和B都不是一个线程;
 
 
 
参考:
http://www.cocoachina.com/ios/20151117/14240.html    这一篇文章讲的很好,刚开始我自己看源码确实理不清这些关系,对着这个一个类一个类的看下去,才终于明白了整个的调用层次;
 
http://www.cnblogs.com/ludashi/p/5588044.html   这篇文章会告诉你每个类都做了什么
 
 

以上是关于Alamofire源码学习的主要内容,如果未能解决你的问题,请参考以下文章

Swift - Alamofire源码解析

Swift - Alamofire源码解析

Swift - Alamofire源码解析

Swift - Alamofire源码解析

Alamofire源码导读一:框架

iOS开发之Alamofire源码深度解析