欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

小白的AFNetWorking之路

发布时间:2025/3/21 编程问答 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 小白的AFNetWorking之路 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

淘汰掉了ASIHTTPRequest和MKNetworkit,AFNetworking完美胜出

起初

新建一个工程HelloWorld,你想在这个工程中通过pod来集成使用第三方库AFNetworking。

使用终端进入工程根目录,然后编辑Podfile:

vim Podfile

【这里你也许会遇到一个问题终端左下角会提示E353:Nothing in register,不要慌,这并不是什么问题,而是自己操作错误,这时候只要按【i】或者【a】进入vi的插入模式就可以编辑了】

这里普及一下vi的工作模式:

1、命令行模式:用光标在字符之间来回移动,进行删除、复制、移动字符等操作,按【i】或者【a】进入插入模式,按【:】(冒号)进入末行模式;

2、插入模式:输入你要编辑的内容,按【esc】返回命令行模式,按【:】(冒号)进入末行模式;

3、末行模式:保存文件或者退出vi,输入【wq】存盘并退出vi,输入【q!】不保存强制退出vi,输入【w:filename】将文件保存为制定的文件名。

结束上述Podfile编辑后,在终端运行

pod install

【 相关命令`pod repo update` or with `pod install --repo-update`】

了解

AFNetworking框架由会话(NSURLSeeion)、网络监听模块(Reachability)、网络安全模块(Security)、请求序列化(Serialization)、响应序列化(Serialization)和UIKit集成模块(UIKit)构成

如图:

库中最核心的类是AFURLSessionManager,使用频率最高的是其子类AFHTTPSessionManager,在该类中包含了负责请求序列化的AFURLRequestSerialization和响应序列化AFURLResponseSerializer,AFURLSessionManager还提供了会话模块NSURLSession、保证网络安全的AFSecurityPolicy、网络监听的AFNetworkReachabilityManager。

如图:

使用

首先在头部导入#import <AFNetworking/AFNetworking.h>

写个get请求

// 实现一个get请求 -(void)makeGetRequest{AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];NSDictionary *headerDic = [NSDictionary dictionaryWithObjectsAndKeys:@"application/json",@"Content-Type", nil];[sessionManager GET:@"http://wna.test.com/app" parameters:nil headers:headerDic progress:^(NSProgress * _Nonnull downloadProgress) {} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {NSLog(@"接口请求成功-- %@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"接口请求失败-- %@",error);}]; }

写个post请求

// 实现一个post请求 - (void)makePostRequest{AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];NSDictionary *headerDic = @{@"nbp-app-name":@"dog",@"Content-Type":@"application/json",};NSDictionary *parames = @{@"methodType":@"GET",@"moduleName":@"app-product",@"url":@"product/new_product_list",};[sessionManager POST:@"http://wna.test.com/app" parameters:parames headers:headerDic progress:^(NSProgress * _Nonnull uploadProgress) {} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {NSData *tempDisplay = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:nil];NSString *result = [[NSString alloc] initWithData:tempDisplay encoding:NSUTF8StringEncoding];NSLog(@"接口请求成功-- %@",result);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"接口请求失败-- %@",error);}]; }

方法的逐级调用

get方法的源码:

- (NSURLSessionDataTask *)GET:(NSString *)URLStringparameters:(nullable id)parametersheaders:(nullable NSDictionary <NSString *, NSString *> *)headersprogress:(nullable void (^)(NSProgress * _Nonnull))downloadProgresssuccess:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))successfailure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure {NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"URLString:URLStringparameters:parametersheaders:headersuploadProgress:nildownloadProgress:downloadProgresssuccess:successfailure:failure];[dataTask resume];return dataTask; }

入参有请求的URL,参数,请求头,进度Block,成功Block和失败Block。在这个方法中初始化了一个NSURLSessionDataTask的类,NSURLSessionDataTask继承自NSURLSessionTask,NSURLSessionDataTask不提供NSURLSessionTask的任何附加功能,他的存在是为了区别于上载NSURLSessionUploadTask和下载NSURLSessionDownloadTask。

继续往下看

- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable id)parametersheaders:(nullable NSDictionary <NSString *, NSString *> *)headersuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgresssuccess:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))successfailure:(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:requestuploadProgress:uploadProgressdownloadProgress:downloadProgresscompletionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {if (error) {if (failure) {failure(dataTask, error);}} else {if (success) {success(dataTask, responseObject);}}}];return dataTask; }

在这个方法的实现里主要做了两个事情:

  • 实例化NSMutableURLRequest对象
  • 实例化NSURLSessionDataTask对象,并返回
  • 在这个方法里是通过一个实现了AFURLRequestSerialization协议的请求序列化实例对象AFHTTPRequestSerializer来调用其实例方法得到一个NSMutableURLRequest对象。

    - (nullable NSMutableURLRequest *)requestWithMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable id)parameterserror:(NSError * _Nullable __autoreleasing *)error;

    我们看下该方法的实现

    - (NSMutableURLRequest *)requestWithMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(id)parameterserror:(NSError *__autoreleasing *)error {NSParameterAssert(method);NSParameterAssert(URLString);// 初识化URLNSURL *url = [NSURL URLWithString:URLString];NSParameterAssert(url);// 初始化RequestNSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];// 设置请求方式mutableRequest.HTTPMethod = method;// 为某些属性赋值【allowsCellularAccess,cachePolicy,HTTPShouldHandleCookies,HTTPShouldUsePipelining,networkServiceType,timeoutInterval】for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];}}// 调用实现的协议mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];return mutableRequest; }

    在实现的协议中,真正的完成了一条完整的请求,请求地址,请求头,请求体

    - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)requestwithParameters:(id)parameterserror:(NSError *__autoreleasing *)error {NSParameterAssert(request);NSMutableURLRequest *mutableRequest = [request mutableCopy];[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {if (![request valueForHTTPHeaderField:field]) {// 设置请求头[mutableRequest setValue:value forHTTPHeaderField:field];}}];// 序列化参数 用&拼接NSString *query = nil;if (parameters) {if (self.queryStringSerialization) {NSError *serializationError;query = self.queryStringSerialization(request, parameters, &serializationError);if (serializationError) {if (error) {*error = serializationError;}return nil;}} else {switch (self.queryStringSerializationStyle) {case AFHTTPRequestQueryStringDefaultStyle:query = AFQueryStringFromParameters(parameters);break;}}}// 如果是GET,HEAD,DELETE 走这边if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {// 将序列化的参数拼到后面if (query && query.length > 0) {mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];}} else {// POST、PUT走这里// #2864: an empty string is a valid x-www-form-urlencoded payloadif (!query) {query = @"";}// 如果没有设置Content-Type,此处默认设置成application/x-www-form-urlencodedif (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];}// 配置请求体[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];}return mutableRequest; }

    上面这块是NSMutableURLRequest的整个过程,下面看下NSURLSessionDataTask

    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)requestuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(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; }

    该方法中通过NSURLSession创建了一个NSURLSessionDataTask对象,并给dataTask添加代理

    在session的初始化中添加了安全锁,保证了线程的安全。

    - (NSURLSession *)session {@synchronized (self) {if (!_session) {_session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];}}return _session; } - (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTaskuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];delegate.manager = self;delegate.completionHandler = completionHandler;dataTask.taskDescription = self.taskDescriptionForSessionTasks;[self setDelegate:delegate forTask:dataTask];delegate.uploadProgressBlock = uploadProgressBlock;delegate.downloadProgressBlock = downloadProgressBlock; }

    上面就是一条完整的调用流程,回到最初的地方[dataTask resume];开始网络请求

    AFN使用技巧

  • 创建一个工具类,继承自AFNetwork的请求管理者
  • 工具类中提供一个单例方法和一个基本的请求路径,提供对GET和POST的请求封装
  • 发送请求使用自己封装的工具类
  • 方便修改,如果修改了底层的依赖框架,只用修改工具类就可以了
  • 相关面试问题:

    AFURLSessionManager主要负责哪些功能?

  • 创建和管理NSURLSession、NSURLSessionTask
  • 实现NSURLSessionDelegate等协议的代理方法
  • 引入AFSecurityPolicy保证请求的网络安全(证书的校验。公钥的验证等)
  • 引入AFNetworkReachabilityManager监听网络状态
  •  

     

     

     

     

     

     

    总结

    以上是生活随笔为你收集整理的小白的AFNetWorking之路的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。