本文首要内容
一.AFNetworking
二.SDWebImageView
三.Reactive Cocoa
四.AsyncDisplayKit
一.AFNetworking
iOS客户端的第三方网络结构
1.1、结构图
在AFNetworking
这个第三方网络库中,首要由会话(即NSURLSession)部分
组成;其次是网络监听模块
,用来监听网络的改变,而且进行相关的逻辑处理;第三部分为网络安全模块
。同时AFNetworking对恳求和呼应进行了序列化的封装,在此之上又有关于UIKit集成模块,如UIKit原生控件分类的增加,以上一切构成了AFNetworking全体结构
。
1.2、首要类联系图
在AFNetworking
库中中心类为AFURLSessionManager
,中心类内部又包括会话NSURLSession
、AFSecurityPolicy
(进行网络证书的校验、公钥的校验等,确保网络安全)、AFNetworkingReachabilityManager
(对网络连接进行监听)等内容。中心类有一个子类AFHTTPSessionManager
,该子类包括AFURLRequestSer ialization
(用来担任根据传进来的参数拼装/拼接最终的成果,即NSMutableU
RLRequest)和AFURLResponseSerialization
(担任呼应序列化,对网络恳求回来成果进行解析,有对应解析办法,如json、image等的)。
总结来说,AFURLSessionManager首要作业
:
- 创建和管理NSURLSession、NSURLSessionTask(对应一个网络恳求);
- 实现NSURLSessionDelegate等协议的署理办法;
- 引进AFSecurityPolicy确保恳求安全;
- 引进AFNetworkingReachabilityManager监控网络状况。
例:发送一个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
担任具体图片的下载器。
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:
到SDWebImageManager
,SDWebImageManagerDelegate
回调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 geDownloader
,imageDownloader:didFinishWithImage:
回调给SDW ebImageManager
告知图片下载完结,告诉一切的downloadDelegates
下载完结,回调给需求的地方展现图片;
9、将图片保存到SDImageCache
中,内存缓存和磁盘缓存同时保存,写文件到磁盘也单独在NSInvocationOperation
中完结,防止拖慢主线程;
-
SDImageCache
在初始化的时分会注册一些消息告诉,在内存正告或退到后台的时分整理内存图片缓存,使用完毕的时分整理过期图片; -
SDWebImagePrefetcher
能够预先下载图片,便利后续使用。
三.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版本
3.1、什么是函数呼应式编程
ReactiveCocoa
是一个函数呼应式编程结构,能够订阅一个信号
就是函数呼应式编程的中心概念。
3.2、信号
- 该结构中的中心类为
RACSignal
。
-
经过父类
RACStream
的组成结构,了解信号 -
信号代表一连串的状况
如下图,信号处于1
状况,因为数据的改变,会从1
状况切换到2
状况,数据再改变会导致信号持续改变,最后是end
。在状况改动时,对应的订阅者RACSubscriber就会收到告诉履行呼应的指令。
-
RACSignal
包括子类RACReturnSignal
、RACDynamicSignal
。以下经过看源码了解信号
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
办法,完毕订阅流程。
3.3.2、RACSubscriber
订阅的内部原理
当发生一个RACSubscriber
类时,会在其内部持有一个成员变量,即didSubscribe
(Block),调用RACSubscriber
时会调用此Block,如下:
{
[RACSignal return:@3];
[RACSignal subScribedNext:^(id x){
NSLog(@"%@",x);
}];
}
四.AsyncDisplayKit
提高iOS界面烘托性能的一个结构
4.1、首要处理问题
- 处理布局的耗时运算
- 处理烘托问题
- 处理UIKit目标 将能够移到子线程中处理的问题移到子线程处理。
4.2、基本原理
- 1、针对ASNode的修改和提交,会对其进行封装并提交到一个全局容器傍边;
- 2、ASDK也在Runloop中注册一个Observer;
- 3、当Runloop进入休眠前,ASDK履行该loop内提交的一切使命。
本文总结
AFNetworking的全体结构是怎样的?⭐️⭐️⭐️
SDWebImage结构是怎样加载图片的?⭐️⭐️⭐️
RAC的信号订阅是什么意思?
ASDK的实现原理是怎样的?⭐️⭐️⭐️
有任何问题,欢迎各位评论指出!觉得博主写的还不错的麻烦点个赞喽