该文章阅读的AFNetworking的版本为3.2.0。web
这个分类提供了对请求周期进行控制的方法,包括进度监控、成功和失败的回调。bash
/**
网络会话管理者对象
*/
@property (nonatomic, strong) AFHTTPSessionManager *sessionManager;
复制代码
/**
异步加载指定请求
*/
- (void)loadRequest:(NSURLRequest *)request
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success
failure:(nullable void (^)(NSError *error))failure;
/**
以指定MIME类型和指定文本编码格式异步加载指定请求
*/
- (void)loadRequest:(NSURLRequest *)request
MIMEType:(nullable NSString *)MIMEType
textEncodingName:(nullable NSString *)textEncodingName
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success
failure:(nullable void (^)(NSError *error))failure;
复制代码
/**
保存任务对象
*/
@property (readwrite, nonatomic, strong, setter = af_setURLSessionTask:) NSURLSessionDataTask *af_URLSessionTask;
复制代码
这两个方法就是经过Runtime的关联对象为分类添加属性保存任务对象网络
- (NSURLSessionDataTask *)af_URLSessionTask {
return (NSURLSessionDataTask *)objc_getAssociatedObject(self, @selector(af_URLSessionTask));
}
- (void)af_setURLSessionTask:(NSURLSessionDataTask *)af_URLSessionTask {
objc_setAssociatedObject(self, @selector(af_URLSessionTask), af_URLSessionTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
复制代码
下面的这四个方法一样是经过关联对象为分类添加属,分别是保存网络会话管理者对象和响应序列化对象session
- (AFHTTPSessionManager *)sessionManager {
static AFHTTPSessionManager *_af_defaultHTTPSessionManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_af_defaultHTTPSessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
_af_defaultHTTPSessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
_af_defaultHTTPSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
});
return objc_getAssociatedObject(self, @selector(sessionManager)) ?: _af_defaultHTTPSessionManager;
}
- (void)setSessionManager:(AFHTTPSessionManager *)sessionManager {
objc_setAssociatedObject(self, @selector(sessionManager), sessionManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (AFHTTPResponseSerializer <AFURLResponseSerialization> *)responseSerializer {
static AFHTTPResponseSerializer <AFURLResponseSerialization> *_af_defaultResponseSerializer = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer];
});
return objc_getAssociatedObject(self, @selector(responseSerializer)) ?: _af_defaultResponseSerializer;
}
- (void)setResponseSerializer:(AFHTTPResponseSerializer<AFURLResponseSerialization> *)responseSerializer {
objc_setAssociatedObject(self, @selector(responseSerializer), responseSerializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
复制代码
- (void)loadRequest:(NSURLRequest *)request
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success
failure:(void (^)(NSError *error))failure
{
// 调用下面的方法
[self loadRequest:request MIMEType:nil textEncodingName:nil progress:progress success:^NSData *(NSHTTPURLResponse *response, NSData *data) {
// 设置字符编码方式为UTF8
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
// 若是响应对象有文本编码方式,就将字符编码方式设置为响应的文本编码方式
if (response.textEncodingName) {
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
if (encoding != kCFStringEncodingInvalidId) {
stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);
}
}
// 将返回的数据进行编码
NSString *string = [[NSString alloc] initWithData:data encoding:stringEncoding];
// 若是设置了成功回调就调用block传递数据
if (success) {
string = success(response, string);
}
// 将字符串编码成二进制数据后返回
return [string dataUsingEncoding:stringEncoding];
} failure:failure];
}
- (void)loadRequest:(NSURLRequest *)request
MIMEType:(NSString *)MIMEType
textEncodingName:(NSString *)textEncodingName
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success
failure:(void (^)(NSError *error))failure
{
// 在debug模式下缺乏参数就crash
NSParameterAssert(request);
// 若是当前已经有任务正在进行或者已经暂停,就取消掉这个任务,并将保存它的属性置空
if (self.af_URLSessionTask.state == NSURLSessionTaskStateRunning || self.af_URLSessionTask.state == NSURLSessionTaskStateSuspended) {
[self.af_URLSessionTask cancel];
}
self.af_URLSessionTask = nil;
// 生成任务
__weak __typeof(self)weakSelf = self;
__block NSURLSessionDataTask *dataTask;
dataTask = [self.sessionManager
dataTaskWithRequest:request
uploadProgress:nil
downloadProgress:nil
completionHandler:^(NSURLResponse * _Nonnull response, id _Nonnull responseObject, NSError * _Nullable error) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
// 若是出错就调用失败回调block
if (error) {
if (failure) {
failure(error);
}
// 若是成功
} else {
// 先调用成功回调block
if (success) {
success((NSHTTPURLResponse *)response, responseObject);
}
// 调用UIWebView加载本地数据的方式进行加载页面
[strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:[dataTask.currentRequest URL]];
// 调用UIWebView代理中的完成加载方法
if ([strongSelf.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
[strongSelf.delegate webViewDidFinishLoad:strongSelf];
}
}
}];
// 用属性保存任务对象
self.af_URLSessionTask = dataTask;
// 若是设置了进度对象,就获取到网络会话管理者的下载进程对象
if (progress != nil) {
*progress = [self.sessionManager downloadProgressForTask:dataTask];
}
// 启动任务
[self.af_URLSessionTask resume];
// 调用UIWebView代理中的开始加载方法
if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
复制代码
看完这个分类的源码,咱们能够看到这个分类作的事就是,手动实现了UIWebView
加载网络数据的过程,从而能够监听进度和经过block回调处理成功与失败的结果。异步
一般,咱们会使用loadRequest:
方法加载指定页面,而后经过UIWebViewDelegate
中的方法监听网页加载的开始、结束与失败。post
而这个分类,经过AFHTTPSessionManager
类手动生成NSURLSessionDataTask
对象下载网页的二进制数据,而后经过loadData: MIMEType: textEncodingName: baseURL:
方法加载已经下载到本地的网页的二进制数据。在这个过程当中经过AFHTTPSessionManager
类中已经实现的方法实现进度的监控、成功和失败的回调。ui
源码阅读系列:AFNetworking编码
源码阅读:AFNetworking(一)——从使用入手atom
源码阅读:AFNetworking(二)——AFURLRequestSerializationspa
源码阅读:AFNetworking(三)——AFURLResponseSerialization
源码阅读:AFNetworking(四)——AFSecurityPolicy
源码阅读:AFNetworking(五)——AFNetworkReachabilityManager
源码阅读:AFNetworking(六)——AFURLSessionManager
源码阅读:AFNetworking(七)——AFHTTPSessionManager
源码阅读:AFNetworking(八)——AFAutoPurgingImageCache
源码阅读:AFNetworking(九)——AFImageDownloader
源码阅读:AFNetworking(十)——AFNetworkActivityIndicatorManager
源码阅读:AFNetworking(十一)——UIActivityIndicatorView+AFNetworking
源码阅读:AFNetworking(十二)——UIButton+AFNetworking
源码阅读:AFNetworking(十三)——UIImageView+AFNetworking
源码阅读:AFNetworking(十四)——UIProgressView+AFNetworking