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”错误。
除了注册protocol
class
之外,我还尝试通过在didFinishLaunchingWithOptions
方法中调用来将类添加到AFHTTPSessionManager
的protocolClasses
:
[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与自定义标头