iOS - 将 AFNetworking 与自定义 NSURLProtocol 类一起使用

Posted

技术标签:

【中文标题】iOS - 将 AFNetworking 与自定义 NSURLProtocol 类一起使用【英文标题】:iOS - Use AFNetworking with custom NSURLProtocol class 【发布时间】:2015-01-26 10:36:28 【问题描述】:

我有一个自定义的NSURLProtocol class 在this tutorial 的帮助下实现。除了名称、数据模型等之外,我的实现与教程中的几乎相同......

本质上,我正在尝试发送HTTP 请求,但不是URL 以“http://”开头,而是需要以“bla://”开头

现在,我正在尝试注册protocol class 并通过AFNetworking framework 使用它,但遇到了一些麻烦。

canInitWithRequest: 方法在某个时候开始返回 NO,此时请求失败,我不断收到“不支持的 URL”错误。

除了注册protocolclass之外,我还尝试通过在didFinishLaunchingWithOptions方法中调用来将类添加到AFHTTPSessionManagerprotocolClasses

[NSURLProtocol registerClass:[MyURLProtocol class]];
NSMutableArray *protocolsArray = [NSMutableArray arrayWithArray:[AFHTTPSessionManager manager].session.configuration.protocolClasses];
[protocolsArray addObject:[MyURLProtocol class]];
[AFHTTPSessionManager manager].session.configuration.protocolClasses = [protocolsArray copy];

我还在应用程序的 info.plist 中的 URL Schemes 字段中添加了 url 方案

仍然没有运气... 我想要做的甚至可能吗?如果是这样,我会错过什么? 谢谢

【问题讨论】:

NSURLProtocol 类中的方法是否被调用? 是的,协议方法似乎工作正常。此外,当我在请求 url 的开头加上“http://”时,服务器会响应(当然响应错误,因为它是错误的协议)。所以请求肯定会被发送。 我刚刚测试了 ryanwa 的建议,它确实有效。 【参考方案1】:

所以,对于其他寻找有关此信息的人:

除了AFURLSessionManager 不使用标准NSURLProtocol 注册这一事实之外,它还处理数组先进先出,而不是像NSURLProtocol 那样的后进先出。

意思是,如果你想覆盖AFURLSessionManager 的行为(比如为了测试目的),你不能只将NSURLProtocol 子类添加到session.configuration.protocolClasses,你必须将它添加到session.configuration.protocolClasses 的开头数组(或至少在您要覆盖/修改的行为之前)。

【讨论】:

正确答案:将行 [protocolsArray addObject:[MyURLProtocol class]]; 更改为 [protocolsArray insertObject:[MyURLProtocol class] atIndex:0]; 应该可以工作。【参考方案2】:

所以,首先@dopcn 是正确的,您需要保留AFHTTPSessionManager 的实例。

@ryanwa 部分正确,您需要在数组的开头插入新协议,但它仍然不起作用,因为在创建 NSURLSession 后无法更改配置。正确的解决方法是使用initWithSessionConfiguration:

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSMutableArray * protocolsArray = [sessionConfiguration.protocolClasses mutableCopy];
[protocolsArray insertObject:[MyURLProtocol class] atIndex:0];
sessionConfiguration.protocolClasses = protocolsArray;
AFHTTPSessionManager * myManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:sessionConfiguration]; //retain this somewhere!

据我所知,您不需要使用registerClass 注册您的NSURLProtocol 子类。这在 iPad Mini 4 上的 ios 9.1 上对我有用。

来自NSURLSession 上的文档:

@property(readonly, copy) NSURLSessionConfiguration *configuration

说明

此会话的配置对象的副本。 (只读)更改配置对象中的可变值 对当前会话没有影响,但可以新建会话 使用修改后的配置对象。

【讨论】:

【参考方案3】:

[AFHTTPSessionManager manager] 不返回单例对象,而是返回一个全新的实例。因此,如果您只是在didFinishLaunchingWithOptions 中为AFHTTPSessionManager 的一个实例设置protocolClasses,但在其他地方使用[AFHTTPSessionManager manager] 创建的另一个实例,则新管理器没有注册您的自定义协议类。这可能会导致问题。

【讨论】:

谢谢!很高兴知道。我已将 AFHTTPSessionManager 实例移动到我的应用程序中的单例实用程序类,但不幸的是,这并没有解决我的问题。顺便说一句,当我输入服务器地址时,示例项目给了我相同的结果。我感觉协议本身的实现有问题……

以上是关于iOS - 将 AFNetworking 与自定义 NSURLProtocol 类一起使用的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 使 UITableView 与自定义单元格在按钮单击时可编辑

UITextView 委托行为与自定义 iOS 键盘 (SwiftKey) 不同

iOS版;以编程方式uicollectionView与自定义标头

socket.io 1.0.0^:使用默认房间与自定义房间进行用户特定的通信

库未加载@rpath/AFNetworking iOS

AFNetworking 3.0 GET 请求在 iOS 中保存到类中