本篇博客是接着上一篇AFNetworking源码解析的后续,如果想对AFNetworking源码有所了解。

请读一下https://www.cnblogs.com/guohai-stronger/p/9191497.html

YTKNetwork的源码详解:https://www.cnblogs.com/guohai-stronger/p/9194519.html

这篇博客主要是对AFNetworking代码进行封装,也是自己在实际项目中所使用过的(对中小型企业或者项目)可直接使用,也会在github上传(偷偷窃喜一下,一直想在github上有所项目,一直没有时间),趁着端午几天有时间,给github贡献点自己力量。本篇读下来大约10-15分钟,欢迎指正。

一.结构解析

最核心(可直接拖拽到新项目中)

(拓展cocoapods的拖入) 拖入之前,需要导入AFNetworking,最好利用cocoapods导入,cocoapods导入时

  1. vim Podfile --->输入i
  1. platform :ios, '8.0'
  2.  
  3. target "targetName" do
  4.  
  5. pod 'AFNetworking'
  6.  
  7. end

(有一点在然后按Esc,并且输入“ :”号进入vim命令模式,然后在冒号后边输入wq)最后pod install。编译一下,拖入项目的类就好了,就不会编译错误。

二.分类讲解

1.Singleton

  1. #import <UIKit/UIKit.h>
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // 申明和定义单例对象:
  4. // AS_SINGLETON( XxxClass );
  5. // DEF_SINGLETON( XxxClass );
  6. #undef AS_SINGLETON
  7. #define AS_SINGLETON( __class ) \
  8. - (__class *)sharedInstance; \
  9. + (__class *)sharedInstance;
  10.  
  11. #undef DEF_SINGLETON
  12. #define DEF_SINGLETON( __class ) \
  13. - (__class *)sharedInstance \
  14. { \
  15. return [__class sharedInstance]; \
  16. } \
  17. + (__class *)sharedInstance \
  18. { \
  19. static dispatch_once_t once; \
  20. static __class * __singleton__; \
  21. dispatch_once( &once, ^{ __singleton__ = [[[self class] alloc] init]; } ); \
  22. return __singleton__; \
  23. }

通过Singleton,来声明和定义单例对象。

声明单例

  1. // 声明单例
  2. AS_SINGLETON(APIClient);

定义单例

  1. // 定义单例
  2. DEF_SINGLETON(APIClient);

2.APIClient.h

(1)请求响应的状态

  1. // 请求响应的状态
  2. typedef NS_ENUM(NSInteger, ApiRequestStatusCode) {
  3. ApiRequestNotReachable = -, // 当前网络已断开
  4. ApiRequestErr = -, // 请求出错
  5. ApiRequestOK = , // 请求成功
  6. };

当时的请求响应状态只有三个,故定义一个枚举表示请求响应的状态。

(2)请求的方法类型

  1. // 请求的方法类型
  2. typedef NS_ENUM(NSInteger, HttpMethod) {
  3. GET = ,
  4. POST = ,
  5. DELETE = ,
  6. PUT = ,
  7. PATH_GET = , // GET请求,填充参数到url上,处理@"user/account/check/{phone}",{phone}这种情况
  8. QUERY_GET = , // GET请求,填充query参数到url上,处理"?a=1&b=2"这种情况
  9. };

(3)请求相应的block

  1. // 请求响应Block
  2. typedef void (^APIClientRequestResponse)(ApiRequestStatusCode requestStatusCode, id JSON);

(4)通过设置代理拦截成功响应数据

  1. @protocol APIClientDelegate <NSObject>
  2.  
  3. @required
  4. // 拦截成功请求响应数据进行处理
  5. - (void)handleSuccessRequest:(id)JSON completion:(void(^)(id aJSON))cb;
  6.  
  7. @end

在.h中还有一些方法属性

  1. // 为处理拦截的响应数据而设置的委托
  2. @property (nonatomic, weak) id<APIClientDelegate> delegate;
  3.  
  4. // 声明单例
  5. AS_SINGLETON(APIClient);
  6.  
  7. // 获取当前的网络状态类型(返回:0-No wifi or cellular(无网络), 1-2G, 2-3G, 3-4G, 4-LTE, 5-wifi)
  8. + (int)networkType;
  9.  
  10. // 网络状态监听,应用当前是否有网络:有返回YES,没有返回NO
  11. + (void)networkReachableWithBlock:(void(^)(BOOL isReachable))block;
  12.  
  13. // 发送请求,返回JSON格式的响应数据
  14. + (void)requestURL:(NSString *)urlString
  15. httpMethod:(HttpMethod)method
  16. params:(NSDictionary *)params
  17. response:(APIClientRequestResponse)response;
  18.  
  19. // 取消掉所有网络请求
  20. + (void)cancelAllRequest;

3.APIClient.m

(1)创建请求管理对象

  1. @property (nonatomic, strong) AFHTTPSessionManager *manager;

(2)获取当前的网络状态类型

  1. // 获取当前的网络状态类型(返回:0-No wifi or cellular(无网络), 1-2G, 2-3G, 3-4G, 4-LTE, 5-wifi)
  2. + (int)networkType {
  3. NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];
  4. NSNumber *dataNetworkItemView = nil;
  5.  
  6. for (id subview in subviews) {
  7. if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
  8. dataNetworkItemView = subview;
  9. break;
  10. }
  11. }
  12. int ret = ;
  13. switch ([[dataNetworkItemView valueForKey:@"dataNetworkType"] integerValue]) {
  14. case :
  15. ret = ;
  16. break;
  17. case :
  18. ret = ;
  19. break;
  20. case :
  21. ret = ;
  22. break;
  23. case :
  24. ret = ;
  25. break;
  26. case :
  27. ret = ;
  28. break;
  29. case :
  30. ret = ;
  31. break;
  32. default:
  33. break;
  34. }
  35. return ret;
  36. }

(3)网络状态监听,应用当前是否有网络

  1. // 网络状态监听,应用当前是否有网络
  2. + (void)networkReachableWithBlock:(void(^)(BOOL isReachable))block {
  3. [[AFNetworkReachabilityManager sharedManager] startMonitoring];
  4.  
  5. [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
  6. switch (status) {
  7. case AFNetworkReachabilityStatusReachableViaWWAN:
  8. case AFNetworkReachabilityStatusReachableViaWiFi: {
  9. if (block) {
  10. block(YES);
  11. }
  12. break;
  13. }
  14. case AFNetworkReachabilityStatusNotReachable: {
  15. if (block) {
  16. block(NO);
  17. }
  18. break;
  19. }
  20. default:
  21. break;
  22. }
  23. }];
  24.  
  25. //结束监听
  26. //[[AFNetworkReachabilityManager sharedManager] stopMonitoring];
  27. }

(3)请求最重要最核心的代码

  1. // 发送请求,返回JSON格式的响应数据
  2. + (void)requestURL:(NSString *)urlString
  3. httpMethod:(HttpMethod)method
  4. params:(NSDictionary *)params
  5. response:(APIClientRequestResponse)response {
  6. if ([APIClient networkType] > ) {
  7. APIClient *client = [APIClient sharedInstance];
  8. if (!client.manager) {
  9. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  10. manager.requestSerializer.timeoutInterval = ;
  11. manager.requestSerializer = [AFHTTPRequestSerializer serializer];
  12. manager.responseSerializer = [AFJSONResponseSerializer serializer];
  13. AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
  14. manager.responseSerializer = responseSerializer;
  15. manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"application/x-www-form-urlencodem", nil];
  16.  
  17. client.manager = manager;
  18. }
  19.  
  20. __weak typeof(self)weakSelf = self;
  21. switch (method) {
  22. case PATH_GET: {
  23. urlString = [APIClient pathGet:urlString params:params];
  24. // //LOG(@"PATH_GET http_url:%@",urlString);
  25. [client.manager GET:urlString
  26. parameters:nil
  27. progress:nil
  28. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  29. __strong typeof(weakSelf)strongSelf = weakSelf;
  30. if (strongSelf) {
  31. [strongSelf handleSuccessRequest:JSON cb:response];
  32. }
  33. }
  34. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  35. if (response) {
  36. response(ApiRequestErr, nil);
  37. }
  38. }];
  39. break;
  40. }
  41. case QUERY_GET: {
  42. urlString = [APIClient queryGet:urlString params:params];
  43. //LOG(@"QUERY_GET http_url:%@",urlString);
  44. [client.manager GET:urlString
  45. parameters:nil
  46. progress:nil
  47. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  48. __strong typeof(weakSelf)strongSelf = weakSelf;
  49. if (strongSelf) {
  50. [strongSelf handleSuccessRequest:JSON cb:response];
  51. }
  52. }
  53. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  54. if (response) {
  55. response(ApiRequestErr, nil);
  56. }
  57. }];
  58. break;
  59. }
  60. case GET: {
  61. // //LOG(@"GET http_url:%@",urlString);
  62. [client.manager GET:urlString
  63. parameters:nil
  64. progress:nil
  65. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  66. __strong typeof(weakSelf)strongSelf = weakSelf;
  67. if (strongSelf) {
  68. [strongSelf handleSuccessRequest:JSON cb:response];
  69. }
  70. }
  71. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  72. if (response) {
  73. response(ApiRequestErr, nil);
  74. //LOG(@"GET http_url:%@",urlString);
  75. }
  76. }];
  77. break;
  78. }
  79. case POST: {
  80. // //LOG(@"POST http_url:%@",urlString);
  81. [client.manager POST:urlString
  82. parameters:params
  83. progress:nil
  84. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  85. __strong typeof(weakSelf)strongSelf = weakSelf;
  86. if (strongSelf) {
  87. [strongSelf handleSuccessRequest:JSON cb:response];
  88. }
  89. }
  90. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  91. // //LOG(@"%@",error);
  92. if (response) {
  93. response(ApiRequestErr, nil);
  94. }
  95. }];
  96. break;
  97. }
  98. case DELETE: {
  99. //LOG(@"DELETE http_url:%@",urlString);
  100. [client.manager DELETE:urlString
  101. parameters:nil
  102. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  103. __strong typeof(weakSelf)strongSelf = weakSelf;
  104. if (strongSelf) {
  105. [strongSelf handleSuccessRequest:JSON cb:response];
  106. }
  107. }
  108. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  109. if (response) {
  110. response(ApiRequestErr, nil);
  111. }
  112. }];
  113. break;
  114. }
  115. case PUT: {
  116. //LOG(@"PUT http_url:%@",urlString);
  117. [client.manager PUT:urlString
  118. parameters:params
  119. success:^(NSURLSessionDataTask * __unused task, id JSON) {
  120. __strong typeof(weakSelf)strongSelf = weakSelf;
  121. if (strongSelf) {
  122. [strongSelf handleSuccessRequest:JSON cb:response];
  123. }
  124. }
  125. failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
  126. if (response) {
  127. response(ApiRequestErr, nil);
  128. }
  129. }];
  130. break;
  131. }
  132. }
  133. } else { // 没有连接网络
  134. if (response)
  135. response(ApiRequestNotReachable, nil);
  136. }
  137. }

(4)统一处理响应数据

  1. // 统一处理响应数据
  2. + (void)handleSuccessRequest:(id)JSON cb:(void(^)(ApiRequestStatusCode requestStatusCode, id JSON))cb {
  3. APIClient *client = [APIClient sharedInstance];
  4. if (client.delegate && [client.delegate respondsToSelector:@selector(handleSuccessRequest:completion:)]) {
  5. [client.delegate handleSuccessRequest:JSON
  6. completion:^(id aJSON) {
  7. if (cb) {
  8. cb(ApiRequestOK, aJSON);
  9. }
  10. }];
  11. } else {
  12. if (cb) {
  13. cb(ApiRequestOK, JSON);
  14. }
  15. }
  16. }

(5)参数拼接

  1. // 填充参数到url上,处理@"user/account/check/{phone}",{phone}这种情况
  2. + (NSString *)pathGet:(NSString *)uri
  3. params:(NSDictionary *)params {
  4. if (nil == uri|| nil == params || params.count <= ) {
  5. return uri;
  6. }
  7. for (NSString *key in params) {
  8. NSString *key2 = [NSString stringWithFormat:@"{%@}",key];
  9. if ([uri rangeOfString:key2].location != NSNotFound) {
  10. uri = [uri stringByReplacingOccurrencesOfString:key2 withString:params[key]];
  11. }
  12. }
  13. return [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  14. }
  15.  
  16. // 填充query参数到url上,处理"?a=1&b=2"这种情况
  17. + (NSString *)queryGet:(NSString *)uri
  18. params:(NSDictionary *)params {
  19. if (nil == uri || nil == params || params.count <= ) {
  20. return uri;
  21. }
  22. NSMutableString *tmpUri = [NSMutableString stringWithString:uri];
  23. int i = ;
  24. for (NSString *key in params) {
  25. if (i == ) {
  26. [tmpUri appendFormat:@"?%@=%@",key, params[key]];
  27. } else {
  28. [tmpUri appendFormat:@"&%@=%@",key, params[key]];
  29. }
  30. i++;
  31. }
  32. return [tmpUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];;
  33. }

(6)取消所有网络请求

  1. // 取消掉所有网络请求
  2. + (void)cancelAllRequest {
  3. APIClient *client = [APIClient sharedInstance];
  4. if (client.manager) {
  5. if (client.manager.operationQueue) {
  6. [client.manager.operationQueue cancelAllOperations];
  7. }
  8. }
  9. }

上面就是代码的主要封装,可以应对中小型企业和App的要求。

三.使用

1.新建API.h继承NSObject

2.在API.m使用

3.在控制器里面调用如下

  1. WS(weakSelf);
  2. if ([APIClient networkType] > ){
  3. //获取个人界面的信息
  4. [API1 getEvaluateMeDataWithCB:^(ApiRequestStatusCode requestStatusCode, id JSON) {
  5. switch (requestStatusCode) {
  6. case ApiRequestOK: {
  7. //正确解析json,以及UI处理break;
  8. }
  9. }
  10. case ApiRequestErr:
  11. [MBProgressHUD showError:kErrTip];
  12. break;
  13. case ApiRequestNotReachable:
  14. [MBProgressHUD showError:kNotReachableTip];
  15. break;
  16. default:
  17. break;
  18. }
  19. }];
  20. }else{
  21. [MBProgressHUD showError:kNotReachableTip];
  22. }

上面就是针对AFNetworking的简单封装,可以满足网络请求的封装。

本次代码的demo已上传git。github地址:https://github.com/zxy1829760/testAF

欢迎指正!!!

下一篇讲述另一篇关于网络封装的YTKNetwork源码解析。

AFNetworking封装-项目使用的更多相关文章

  1. iOS | AFNetworking封装

    为大家分享一个IOS处理网络请求,网络上传,网络下载等功能全面的一个第三方框架-AFNetworking,这是一个使用非常方便的网络框架. 最新的版本是基于NSURLSession,原来的NSURLC ...

  2. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(一)

    1,其实早就想把这些东西给封装封装的,一直没有时间,今天刚好项目进入到测试阶段了,Bug同事在哪儿测试的飞起,但发现提bug的尽然是我(得意脸),然后上午把ios的包测试了一下,顺便把服务器给测挂了( ...

  3. AFNetworking封装思路简析

    http://blog.csdn.net/qq_34101611/article/details/51698473 一.AFNetworking的发展 1. AFN 1.0版本 AFN 的基础部分是 ...

  4. C# .NET更智能的数据库操作封装项目

    前面两篇文章介绍了框架的思路及里面大概的实现过程,那时候忘记上传项目,就补发一下.顺便介绍下框架使用方式,并分析下框架使用的优缺点. 先发一下前两章的链接 篇一:http://www.cnblogs. ...

  5. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(三)

    1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇 2,Dagger ...

  6. 基于AFNetworking封装的网络请求工具类【原创】

    今天给大家共享一个我自己封装的网络请求类,希望能帮助到大家. 前提,导入AFNetworking框架, 关于修改AFN源码:通常序列化时做对text/plan等的支持时,可以一劳永逸的修改源代码,在a ...

  7. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)

    1,昨天我们基本上把MVP给封装起来了,今天接着昨天的东西来结合RxJava把Retrofit把网络框架简单的封装一下,先看一下我们今天实现的效果: 哈哈 ,还是昨天的效果,好吧 ,我认错. 2,由于 ...

  8. 基于AFNetWorking封装一个网络请求数据的类

    1.新建一个继承于NSObject类的类,在.h文件中 #import "AFHTTPRequestOperationManager.h" //定义两个block来接收请求成功和失 ...

  9. 单例:用AFNetworking封装举例

    创建单例的方式 import AFNetworking class NetworkTools: AFHTTPSessionManager { //let是线程安全的 //使用单例实例只需要拿到Netw ...

随机推荐

  1. web网站在不同设备下进行缩放

    <script> function calculatescale() { var phoneWidth = parseInt(window.screen.width); var phone ...

  2. c++实现对windwos 下socket 的封装(实现封包及拆包处理)

    SuperSocket.h #pragma once #include<string> #include<iostream> #include <WINSOCK2.H&g ...

  3. 在已有数据的表中添加id字段并且自增

    各位大牛,小弟在开发过程中,遇到了这样一个问题,由于新功能的增加需要使原有的一张表的结构作出调整,需要添加一个id主键字段,但是因为表里有很多数据了,所以,怎样才能添加这个字段,并且使原有的数据也能够 ...

  4. Redis安装和实际应用

    上次介绍了Redis的来龙去脉以及相关一些情况,点击回顾<深入浅出Redis>,接下来我们再讲讲Redis的安装和实际应用. 一.Redis的安装 下载安装包,redis-3.2.9.ta ...

  5. MySQL索引优化看这篇文章就够了!

    阅读本文大概需要 5 分钟. 来源:cnblogs.com/songwenjie/p/9410009.html 本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引 ...

  6. phpspreadsheet导出数据到Excel

    之前我们使用PHP导出Excel数据时使用的是PHPExcel库,但是phpoffice已经官方宣布PHPExcel已经被废弃不在维护,推荐使用phpspreadsheet,如下图所示 我们可以通过c ...

  7. 第58节:Java中的图形界面编程-GUI

    欢迎到我的简书查看我的文集 前言: GUI是图形用户界面,在Java中,图形用户界面我们用GUI表示,而GUI的完整英文为: Graphical User Interface(图形用户接口), 所谓图 ...

  8. CSS揭秘—多重边框(二)

    前言: 所有实例均来自<CSS揭秘>,该书以平时遇到的疑难杂症为引,提供解决方法,只能说秒极了,再一次刷新了我对CSS的认知 该书只提供了关键CSS代码,虽然有在线示例代码链接,但访问速度 ...

  9. Python 函数中参数的分类及使用

    ######################非固定参数################## #第一种方式:def send_alert(msg,*users):##*users 是非固定参数,将传过来 ...

  10. TS - 解决问题的一些方法

    How to resolve the problem? 获取基本的相关信息(后续处理问题的基础)  在怎样的背景环境下?发生了怎样的问题? 如果无法清楚地辨别或陈述问题的基本信息,那么,此时要面对的将 ...