本文首要内容

一.AFNetworking
二.SDWebImageView
三.Reactive Cocoa
四.AsyncDisplayKit

全方位剖析iOS高级技术问题(十二)之第三方库

一.AFNetworking

iOS客户端的第三方网络结构

1.1、结构图

AFNetworking这个第三方网络库中,首要由会话(即NSURLSession)部分组成;其次是网络监听模块,用来监听网络的改变,而且进行相关的逻辑处理;第三部分为网络安全模块。同时AFNetworking对恳求和呼应进行了序列化的封装,在此之上又有关于UIKit集成模块,如UIKit原生控件分类的增加,以上一切构成了AFNetworking全体结构

全方位剖析iOS高级技术问题(十二)之第三方库

1.2、首要类联系图

AFNetworking库中中心类为AFURLSessionManager,中心类内部又包括会话NSURLSessionAFSecurityPolicy(进行网络证书的校验、公钥的校验等,确保网络安全)、AFNetworkingReachabilityManager(对网络连接进行监听)等内容。中心类有一个子类AFHTTPSessionManager,该子类包括AFURLRequestSer ialization(用来担任根据传进来的参数拼装/拼接最终的成果,即NSMutableU RLRequest)和AFURLResponseSerialization(担任呼应序列化,对网络恳求回来成果进行解析,有对应解析办法,如json、image等的)。

总结来说,AFURLSessionManager首要作业

  • 创建和管理NSURLSession、NSURLSessionTask(对应一个网络恳求);
  • 实现NSURLSessionDelegate等协议的署理办法;
  • 引进AFSecurityPolicy确保恳求安全;
  • 引进AFNetworkingReachabilityManager监控网络状况。

全方位剖析iOS高级技术问题(十二)之第三方库

例:发送一个GET方式的HTTP恳求要害代码

// "AFHTTPSessionManager.m"
#pragma mark - GET
- (NSURLSessionDataTask *)GET:(NSString *)URLString
                    parameters:(nullable id)parameters
                    headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                    progress:(nullable void (^)(NSProgress * _Nonnull))downloadProgress
                     success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                     failure:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))failure {
    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
                                                        URLString:URLString
                                                       parameters:parameters
                                                          headers:headers
                                                   uploadProgress:downloadProgress
                                                          success:success
                                                          failure:failure];
    [dataTask resume];
    return dataTask;
}
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                   URLString:(NSString *)URLString
                   parameters:(nullable id)parameters
                    headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                 uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                    success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                    failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure {
  NSError *serializationError = nil;
  NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
  for (NSString *headerField in headers.keyEnumerator) {
    [request setValue:headers[headerField] forHTTPHeaderField:headerField];
  }
  if (serializationError) {
    if (failure) {
      dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
        failure(nil, serializationError);
      });
    }
    return nil;
  }
  __block NSURLSessionDataTask *dataTask = nil;
  dataTask = [self dataTaskWithRequest:request
             uploadProgress:uploadProgress
            downloadProgress:downloadProgress
           completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
    if (error) {
      if (failure) {
        failure(dataTask, error);
      }
    } else {
      if (success) {
        success(dataTask, responseObject);
      }
    }
  }];
  return dataTask;
}
// "AFURLRequestSerialization.m"
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                URLString:(NSString *)URLString
                parameters:(id)parameters
                  error:(NSError *__autoreleasing *)error {
    NSParameterAssert(method);
  NSParameterAssert(URLString);
  NSURL *url = [NSURL URLWithString:URLString];
  NSParameterAssert(url);
  NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
  mutableRequest.HTTPMethod = method;
  for (NSString *keyPath in self.mutableObservedChangedKeyPaths) {
    [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
  }
  mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
    return mutableRequest;
}
// "AFURLSessionManager.m"
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
               uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
              completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler {
  NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];
  [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
  return dataTask;
}

二.SDWebImage

一个异步下载图片而且支撑缓存的结构

2.1、架构简图

SDWebImage结构中首要封装了一些UIKit的分类办法。其中SDWebImageManage r为其中心作业类,SDImageCache担任处理图片的缓存(包括磁盘缓存和内存缓存管理),SDWebImageDownloader担任具体图片的下载器。

全方位剖析iOS高级技术问题(十二)之第三方库

2.2、加载图片的流程

详细流程描述

1、加载图片的进口办法为setImageWithURL:placeholderImage:option s:,先显现默认占位图placeholderImage
2、然后SDWebImageManager根据URL开端处理图片,调用办法downlo adWithURL:delegate:options:userInfo:,经过SDImageCache从缓存查找图片是否现已下载queryDiskCacheForKey:delegate:userInfo:; 3、先从内存图片缓存查找是否有图片,假如内存汇总现已有图片缓存, SDImageCacheDelegate回调imageCache:didFindImage:forKey:userI nfo:SDWebImageManagerSDWebImageManagerDelegate回调webI mageManager:didiFinishWithImage:UIImageView+WebCache等前端展现图片;
4、假如内存中没有,生成NSInvocationOperation增加到队列,开端从磁盘查找图片是否现已缓存;
5、根据URLKey在磁盘缓存目录下尝试读取图片文件,这一步是在NSOperation进行的操作,所以回主线程进行成果回调notifyDelegate:。假如从磁盘读取到了图片,将图片增加到内存缓存中(假如空闲内存过小,会先清空内存缓存),SDImageCacheDelegate回调imageCache:didFindImage:forKey:userInfo:,进而回调展现图片; 6、假如从磁盘缓存目录读取不到图片,阐明一切缓存都不存在该图片,需求下载图片,回调imageCache:didNotFindImageForKey:userIn fo:
7、同享或重新生成一个下载器SDWebImageDownloader开端下载图片,图片下载由NSURLConnection来做,实现相关delegate来判别图片下载中、下载完结和下载失利。connection:didReceiveData:中利用ImageIO做了按图片下载进度加载作用。connectionDidFinishLoading:数据下载完结后交给SDWebImageDecoder做图片解码处理。图片解码处理在一个NSOperationQueue完结,不会拖慢主线程UI,如有需求对下载的图片进行二次处理,最好也在这里完结,效率会高许多;
8、在主线程notifyDelegateOnMainThreadWithInfo:宣告解码完结, imageDecoder:didFinishDecodingImage:userInfo:回调给SDWebIma geDownloaderimageDownloader:didFinishWithImage:回调给SDW ebImageManager告知图片下载完结,告诉一切的downloadDelegates下载完结,回调给需求的地方展现图片;
9、将图片保存到SDImageCache中,内存缓存和磁盘缓存同时保存,写文件到磁盘也单独在NSInvocationOperation中完结,防止拖慢主线程;

  • SDImageCache在初始化的时分会注册一些消息告诉,在内存正告或退到后台的时分整理内存图片缓存,使用完毕的时分整理过期图片;
  • SDWebImagePrefetcher能够预先下载图片,便利后续使用。

全方位剖析iOS高级技术问题(十二)之第三方库

三.ReactiveCocoa

函数呼应式编程结构

编程思维介绍

  • 函数式编程(Functional Programming):
    1、把操作尽量写成一系列嵌套的函数或者办法调用;
    2、每个办法必须有回来值(自身目标),把函数或者Block当作参数,block参数(需求操作的值)block回来值(操作成果),即每一步都需求有成果。
  • 呼应式编程(Reactive Programming): 1、不需求考虑调用顺序,只需求知道考虑成果,即一个改动就会使成果改; 2、典型比如(AutoLayout):aView上增加子view,当aView束缚发生改变时,子view也会随之改动。

怎么导入Reactive Cocoa结构
通常使用CocoaPods导入。

  • ReactiveObjC — 对应的是RAC的OC版本
  • Reactive Cocoa — 对应的是RAC的swift版本

全方位剖析iOS高级技术问题(十二)之第三方库

3.1、什么是函数呼应式编程

ReactiveCocoa是一个函数呼应式编程结构,能够订阅一个信号就是函数呼应式编程的中心概念。

全方位剖析iOS高级技术问题(十二)之第三方库

3.2、信号

  • 该结构中的中心类为RACSignal

全方位剖析iOS高级技术问题(十二)之第三方库

  • 经过父类RACStream的组成结构,了解信号

    全方位剖析iOS高级技术问题(十二)之第三方库

  • 信号代表一连串的状况
    如下图,信号处于1状况,因为数据的改变,会从1状况切换到2状况,数据再改变会导致信号持续改变,最后是end

      在状况改动时,对应的订阅者RACSubscriber就会收到告诉履行呼应的指令。
    

全方位剖析iOS高级技术问题(十二)之第三方库

  • RACSignal包括子类RACReturnSignalRACDynamicSignal。以下经过看源码了解信号

RACDynamicSignal

// RACReturnSignal.m
+ (RACSignal *)return:(id)value {
    ......
    RACReturnSignal *signal = [[self alloc] init];
    signal->_value = value;
    ......
}

RACDynamicSignal

// RACSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    return [RACDynamicSignal createSignal: didSubscribe];
}
// RACDynamicSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}

3.3、订阅

  • 订阅者RACSubscriber

3.3.1 、订阅的逻辑流程

首要开端订阅一个信号RACSignal,然后调用RACSignal-subscriveNext:办法,该办法中会发生一个RACSubscriber类,调用RACSignal-sendNext:办法,在-sendNext:办法内部又会调用-sendCompleted办法,完毕订阅流程。

全方位剖析iOS高级技术问题(十二)之第三方库

3.3.2、RACSubscriber订阅的内部原理

当发生一个RACSubscriber类时,会在其内部持有一个成员变量,即didSubscribe(Block),调用RACSubscriber时会调用此Block,如下:

{
    [RACSignal return:@3];
    [RACSignal subScribedNext:^(id x){
        NSLog(@"%@",x);
    }];
}

全方位剖析iOS高级技术问题(十二)之第三方库

四.AsyncDisplayKit

提高iOS界面烘托性能的一个结构

4.1、首要处理问题

  • 处理布局的耗时运算
  • 处理烘托问题
  • 处理UIKit目标 将能够移到子线程中处理的问题移到子线程处理。
    全方位剖析iOS高级技术问题(十二)之第三方库

4.2、基本原理

  • 1、针对ASNode的修改和提交,会对其进行封装并提交到一个全局容器傍边;
  • 2、ASDK也在Runloop中注册一个Observer;
  • 3、当Runloop进入休眠前,ASDK履行该loop内提交的一切使命。

全方位剖析iOS高级技术问题(十二)之第三方库

本文总结

AFNetworking的全体结构是怎样的?⭐️⭐️⭐️

SDWebImage结构是怎样加载图片的?⭐️⭐️⭐️

RAC的信号订阅是什么意思?

ASDK的实现原理是怎样的?⭐️⭐️⭐️

有任何问题,欢迎各位评论指出!觉得博主写的还不错的麻烦点个赞喽