使用AFNetworking框架遇到的一个经典bug的解决方案

以上为个人愚见, 如有不妥,望大家斧正!!!
本文的GitHub源码下载地址:
https://github.com/DXSmile/Bug---AFNetworking.git

如需转载,请注明转载自DXSmile
GitHub项目https://github.com/DXSmile/Bug---AFNetworking.git

阐述:

在获取网络数据的时候, 我们一般会使用到一个非常著名的框架: AFNetworking框架, 可以说,这是作为iOS攻城狮必备的框架之一;
这个框架是非常强大的一个框架, 对于发送异步请求来说,简直没有比这个更好用的了, 不过,在使用的过程中,我们可能会遇到这样一个bug: 如下

连接出错 Error Domain=com.alamofire.error.serialization.response Code=-1016 
"Request failed: unacceptable content-type: text/html" UserInfo=
{com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7f93fad1c4b0> 
{ URL: http://c.m.163.com/nc/article/headline/T1348647853363/0-140.html } 
{ status code: 200, headers { .....}
...... 
 22222c22 626f6172 64696422 3a226e65 77735f73 68656875 69375f62 6273222c 22707469 6d65223a 22323031 362d3033 2d303320 31313a30 323a3435 227d5d7d>,
 NSLocalizedDescription=Request failed: unacceptable content-type: text/html}

说明:

由于数据很多,所以返回的请求体,和响应体部分我用省略号(......)代替了, 但是,通过上面的返回的信息,我们不难看出,状态码是200, 而且也有一堆数据, 但是在tableviewCell中就是没有显示, 在最后的时候还出现"NSLocalizedDescription=Request failed: unacceptable content-type: text/html} " 这样一句话;

分析:那么这个错误是什么原因造成的呢?

通过这句话:unacceptable content-type: text/html,我们可以看出报错原因:是不接收的内容类型,也就是说AFNetworking框架不支持解析text/html这种格式. 那么怎样解决呢?

首先我们需要明白: AFNetworking为什么能够解析服务器返回的东西呢?

因为manager有一个responseSerializer属性.它只设置了一些固定的解析格式.其中不包含text/html这种数据的格式.因为解析报错了.
我们来看一下AFNetworking解析格式的底层:

 self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

通过底层,我们也可以看见,确实是没有text/html这种数据的格式的,

那如何解决这个问题呢?

错误的解决方法
下面我尝试了三种方法:

解决方法1: 直接给acceptableContentTypes属性添加类型

解决之前:

 self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
解决之前

着手解决:

   AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManagermanager];

    // 添加 text/html 类型到可接收内容类型中
    mgr.responseSerializer.acceptableContentTypes= [NSSetsetWithObjects:@"text/html", nil];

运行结果:

解决之后:

通过执行结果可以很明显的看得出,我们已经非常成功的获取到了数据;

对方法1的思考:

**首先,我们可以明显的看出,方法1确实是可以解决问题的,但是这样解决真的好吗? 不一定!
为什么呢? 很简单, 如果我们只是发送一条网络请求,无疑方法1是最恰当的解决方案了, 但是实际开发中,我们不可能只发一次请求, 那么就需要我们每次发请求的时候都来写一次这些代码; 当然,如果您愿意写,那我也没办法多说什么了;
很显然,这个方法是存在不足的! **

于是我们有了第二种方法:

解决办法2: 直接到框架的源代码中添加类型

解决之前:

 self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

解决之后:

 self.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"application/json", @"text/json" ,@"text/javascript", nil];
分析方法2:

不得不说,这也是一种办法, 而且釜底抽薪,效果方面呢,当然也是显而易见了, 但是, 注意了,这个方法2 又真的恰当吗? 真的好吗?

我们来假设一种情况, 而且实际开发中必然会发生的情况: 这个框架更新了!!!
对,就是更新了!!! 更新了显然又会回到之前的状态
傻眼了吧? **
实际开发中,我们都会用cocoaPods来管理我们的第三方框架, 当某个框架更新之后, cocoaPods会下载最新的框架源码镶嵌到我们的项目中, 我们并不能保证AFNetworking这个框架一定会把我们需要的类型添加上去, 所以
每一次更新,我们都需要针对源码再做一次修改**
很显然,这也是费力不讨好的;

那么有没有一劳永逸的方法呢? 别急,马上就来!!!

解决办法3: 自定义一个manager ,拓展一个类型

>>这里需要考虑到两种情况: 如下
>1. 如果你的APP只需要适配iOS7.0之前的版本,为了能够适配旧系统,需要使用 AFHTTPRequestOperationManager
>2. 如果你的APP只需要适配iOS7.0之后的版本,那么你需要 自定义的类是继承AFHTTPSessionManager的

这里我只简单的介绍iOS7.0之后的版本,

1> 自定义manager,继承自AFHTTPSessionManager

@interface DXHTTPManager : AFHTTPSessionManager

2> 在.m文件中,重写父类的manager方法 目的 : 添加类型

+ (instancetype)manager {
    DXHTTPManager *mgr = [super manager];
    // 创建NSMutableSet对象
    NSMutableSet *newSet = [NSMutableSet set];
    // 添加我们需要的类型 
    newSet.set = mgr.responseSerializer.acceptableContentTypes;
    [newSet addObject:@"text/html"];
    
    // 重写给 acceptableContentTypes赋值
    mgr.responseSerializer.acceptableContentTypes = newSet;
    
    return mgr;
}

3> 在发送请求的时候,使用我们自定义的类来发送请求

[[DXHTTPManager manager] GET:@"http://...." 
parameters:nil success:^(AFHTTPRequestOperation *operation, NSDictionary * responseObject) 
{
    NSLog(@"请求成功 -- %@",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"请求失败 -- %@",error);
}];

执行结果:

方法3执行结果:
结论:

**1. 使用方法3来解决这个bug,虽然看似比第一种,第二种要繁琐一些,实则可拓展性,和维护方面,要好得多,以后我们开发项目的时候, 只需要将我们自定义的这个类拖进去就可以了, 假如有需要新的类型的时候, 也只是简单的多配置一下类型即可, **
2.此外方法3还有一个好处,我们假设一个情景: 如果有一天我们使用的这个AFNetworking框架不再更新了,甚至作废了呢? 这种可能性还是有的,如果我们用方法1和方法2的话, 那个时候你会在项目中看见一堆一堆的bug,
而如果我们使用的方法3的话,那么只需要简单的将继承的类更换成我们最新使用的框架里面的类,然后做一些简单的配置即可,这样维护起来的成本自然就轻松了,

3.而这也正是我们代码重构, 和优化项目架构的思路之一!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,382评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 昨天晚上正巧看到参姐的公众号推送消息,说晚上有私房课,主要讲讲日事清的日程规划。我想最近确实需要听听日程规划,对于...
    洁_寞碎阅读 236评论 0 0
  • 有个朋友今天找我聊天,郁闷的她没有向我大倒苦水,而是把她的坏心情一点一点地向我流淌出来。我能感受她的压抑,劝她别...
    YKmonica阅读 379评论 0 0
  • 有一个人,算不上认识,但却熟悉,我知道,他每天都会出现在一个地方,即使我不常去那,但心里却很安心。这两天,他再...
    朝歌非烨阅读 154评论 0 0