本篇博客是接着上一篇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导入时

vim Podfile     --->输入i
platform :ios, '8.0'

target "targetName" do

pod 'AFNetworking'

end

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

二.分类讲解

1.Singleton

#import <UIKit/UIKit.h>
////////////////////////////////////////////////////////////////////////////////
// 申明和定义单例对象:
// AS_SINGLETON( XxxClass );
// DEF_SINGLETON( XxxClass );
#undef AS_SINGLETON
#define AS_SINGLETON( __class ) \
- (__class *)sharedInstance; \
+ (__class *)sharedInstance; #undef DEF_SINGLETON
#define DEF_SINGLETON( __class ) \
- (__class *)sharedInstance \
{ \
return [__class sharedInstance]; \
} \
+ (__class *)sharedInstance \
{ \
static dispatch_once_t once; \
static __class * __singleton__; \
dispatch_once( &once, ^{ __singleton__ = [[[self class] alloc] init]; } ); \
return __singleton__; \
}

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

声明单例

// 声明单例
AS_SINGLETON(APIClient);

定义单例

// 定义单例
DEF_SINGLETON(APIClient);

2.APIClient.h

(1)请求响应的状态

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

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

(2)请求的方法类型

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

(3)请求相应的block

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

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

@protocol APIClientDelegate <NSObject>

@required
// 拦截成功请求响应数据进行处理
- (void)handleSuccessRequest:(id)JSON completion:(void(^)(id aJSON))cb; @end

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

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

3.APIClient.m

(1)创建请求管理对象

@property (nonatomic, strong) AFHTTPSessionManager *manager;

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

// 获取当前的网络状态类型(返回:0-No wifi or cellular(无网络), 1-2G, 2-3G, 3-4G, 4-LTE, 5-wifi)
+ (int)networkType {
NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];
NSNumber *dataNetworkItemView = nil; for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
dataNetworkItemView = subview;
break;
}
}
int ret = ;
switch ([[dataNetworkItemView valueForKey:@"dataNetworkType"] integerValue]) {
case :
ret = ;
break;
case :
ret = ;
break;
case :
ret = ;
break;
case :
ret = ;
break;
case :
ret = ;
break;
case :
ret = ;
break;
default:
break;
}
return ret;
}

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

// 网络状态监听,应用当前是否有网络
+ (void)networkReachableWithBlock:(void(^)(BOOL isReachable))block {
[[AFNetworkReachabilityManager sharedManager] startMonitoring]; [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi: {
if (block) {
block(YES);
}
break;
}
case AFNetworkReachabilityStatusNotReachable: {
if (block) {
block(NO);
}
break;
}
default:
break;
}
}]; //结束监听
//[[AFNetworkReachabilityManager sharedManager] stopMonitoring];
}

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

// 发送请求,返回JSON格式的响应数据
+ (void)requestURL:(NSString *)urlString
httpMethod:(HttpMethod)method
params:(NSDictionary *)params
response:(APIClientRequestResponse)response {
if ([APIClient networkType] > ) {
APIClient *client = [APIClient sharedInstance];
if (!client.manager) {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = ;
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.responseSerializer = responseSerializer;
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"application/x-www-form-urlencodem", nil]; client.manager = manager;
} __weak typeof(self)weakSelf = self;
switch (method) {
case PATH_GET: {
urlString = [APIClient pathGet:urlString params:params];
// //LOG(@"PATH_GET http_url:%@",urlString);
[client.manager GET:urlString
parameters:nil
progress:nil
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (response) {
response(ApiRequestErr, nil);
}
}];
break;
}
case QUERY_GET: {
urlString = [APIClient queryGet:urlString params:params];
//LOG(@"QUERY_GET http_url:%@",urlString);
[client.manager GET:urlString
parameters:nil
progress:nil
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (response) {
response(ApiRequestErr, nil);
}
}];
break;
}
case GET: {
// //LOG(@"GET http_url:%@",urlString);
[client.manager GET:urlString
parameters:nil
progress:nil
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (response) {
response(ApiRequestErr, nil);
//LOG(@"GET http_url:%@",urlString);
}
}];
break;
}
case POST: {
// //LOG(@"POST http_url:%@",urlString);
[client.manager POST:urlString
parameters:params
progress:nil
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
// //LOG(@"%@",error);
if (response) {
response(ApiRequestErr, nil);
}
}];
break;
}
case DELETE: {
//LOG(@"DELETE http_url:%@",urlString);
[client.manager DELETE:urlString
parameters:nil
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (response) {
response(ApiRequestErr, nil);
}
}];
break;
}
case PUT: {
//LOG(@"PUT http_url:%@",urlString);
[client.manager PUT:urlString
parameters:params
success:^(NSURLSessionDataTask * __unused task, id JSON) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf handleSuccessRequest:JSON cb:response];
}
}
failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (response) {
response(ApiRequestErr, nil);
}
}];
break;
}
}
} else { // 没有连接网络
if (response)
response(ApiRequestNotReachable, nil);
}
}

(4)统一处理响应数据

// 统一处理响应数据
+ (void)handleSuccessRequest:(id)JSON cb:(void(^)(ApiRequestStatusCode requestStatusCode, id JSON))cb {
APIClient *client = [APIClient sharedInstance];
if (client.delegate && [client.delegate respondsToSelector:@selector(handleSuccessRequest:completion:)]) {
[client.delegate handleSuccessRequest:JSON
completion:^(id aJSON) {
if (cb) {
cb(ApiRequestOK, aJSON);
}
}];
} else {
if (cb) {
cb(ApiRequestOK, JSON);
}
}
}

(5)参数拼接

// 填充参数到url上,处理@"user/account/check/{phone}",{phone}这种情况
+ (NSString *)pathGet:(NSString *)uri
params:(NSDictionary *)params {
if (nil == uri|| nil == params || params.count <= ) {
return uri;
}
for (NSString *key in params) {
NSString *key2 = [NSString stringWithFormat:@"{%@}",key];
if ([uri rangeOfString:key2].location != NSNotFound) {
uri = [uri stringByReplacingOccurrencesOfString:key2 withString:params[key]];
}
}
return [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
} // 填充query参数到url上,处理"?a=1&b=2"这种情况
+ (NSString *)queryGet:(NSString *)uri
params:(NSDictionary *)params {
if (nil == uri || nil == params || params.count <= ) {
return uri;
}
NSMutableString *tmpUri = [NSMutableString stringWithString:uri];
int i = ;
for (NSString *key in params) {
if (i == ) {
[tmpUri appendFormat:@"?%@=%@",key, params[key]];
} else {
[tmpUri appendFormat:@"&%@=%@",key, params[key]];
}
i++;
}
return [tmpUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];;
}

(6)取消所有网络请求

// 取消掉所有网络请求
+ (void)cancelAllRequest {
APIClient *client = [APIClient sharedInstance];
if (client.manager) {
if (client.manager.operationQueue) {
[client.manager.operationQueue cancelAllOperations];
}
}
}

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

三.使用

1.新建API.h继承NSObject

2.在API.m使用

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

 WS(weakSelf);
if ([APIClient networkType] > ){
//获取个人界面的信息
[API1 getEvaluateMeDataWithCB:^(ApiRequestStatusCode requestStatusCode, id JSON) {
switch (requestStatusCode) {
case ApiRequestOK: {
//正确解析json,以及UI处理break;
}
}
case ApiRequestErr:
[MBProgressHUD showError:kErrTip];
break;
case ApiRequestNotReachable:
[MBProgressHUD showError:kNotReachableTip];
break;
default:
break;
}
}];
}else{
[MBProgressHUD showError:kNotReachableTip];
}

上面就是针对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. Charles配置抓取HTTPS请求的Android配置

    关于android手机在mac版charles上抓不到包这个问题困扰了很久,查阅了很多资料,发现是android7.0系统安全策略问题. Charles抓包正常流程1.在手机上配置证书 点击后:直接在 ...

  2. POJ3040--Allowance(贪心)

    http://poj.org/problem?id=3040 思路: 输入时,如果有大于c的,直接把数量加到结果中,不把他加到数组中 把钱按面值排序 想取最大面额的钱,保证取到的钱小于等于c 然后取最 ...

  3. app -webkit-box-orient: vertical 打包后不显示

    先说明问题是什么: -webkit-box-orient: vertical 这个属性在本地运行调试是存在的,但是打包后这个属性消失了: 解决办法: 1.将-webkit-box-orient: ve ...

  4. C#-Database-连接

    using System.Data; using System.Data.SqlClient; //先打开两个类库文件 SqlConnection con = new SqlConnection(); ...

  5. FPGA中带优先级的if else if与不带优先级的case的探讨

    我们知道在书本上都说让我们尽量使用不带优先级的的数据选择器,今天我们就来探讨一下二者的区别. 例子1:带优先级的的数据选择器,综合成功,且没有任何警告. module detection_prio # ...

  6. python基础学习记录一

    1.如果脚本中带有中文(中文注释或者中文字符串,中文字符串前面需要在前面加u),且需要在文件头注明编码,并将UTF-8编码格式 #-*-coding:utf-8 -*- printf u'你好,WOR ...

  7. linux 性能优化

    linux的性能优化: 1.CPU,MEM 2.DISK--RAID 3.网络相关的外设,网卡 linux系统性能分析: top:linux系统的负载,CPU,MEM,SWAP,占用CPU和内存比较的 ...

  8. CS61A hw01

    前不久在知乎上看到CS61A 和CS61B spring18 开课的消息.上去看了一眼,发现真的不错,所有proj hw都可以本地测试!也就是说除了没有课程成绩和官方讨论区和TA解答外,这个课完全可以 ...

  9. 每天学点SpringCloud(十二):Zipkin全链路监控

    Zipkin是SpringCloud官方推荐的一款分布式链路监控的组件,使用它我们可以得知每一个请求所经过的节点以及耗时等信息,并且它对代码无任何侵入,我们先来看一下Zipkin给我们提供的UI界面都 ...

  10. 吴恩达机器学习笔记34-模型选择和交叉验证集(Model Selection and Train_Validation_Test Sets)

    假设我们要在10 个不同次数的二项式模型之间进行选择: 显然越高次数的多项式模型越能够适应我们的训练数据集,但是适应训练数据集并不代表着能推广至一般情况,我们应该选择一个更能适应一般情况的模型.我们需 ...