如何确保使用了我的自定义 URL 协议?

Posted

技术标签:

【中文标题】如何确保使用了我的自定义 URL 协议?【英文标题】:How to make sure, that my custom URL protocol is used? 【发布时间】:2017-05-22 15:14:50 【问题描述】:

根据NSURLSessionConfiguration::protocolClasses 的文档,不保证将使用我的自定义url 协议。如何确保在将其设置为 protocolClasses 属性时使用它?

在处理请求之前,NSURLSession 对象会搜索 首先是默认协议,然后检查您的自定义协议,直到它 找到一个能够处理指定请求的人。它使用 canInitWithRequest: 类方法返回 YES 的协议, 表示该类能够处理指定的 请求。

我无法使用单一 URL 协议设置数组,因为它具有 canInitWithRequest: 方法的逻辑并且可能无法处理所有请求。

NSArray *currentProtocolClasses = sessionConfiguration.protocolClasses ?: @[];
NSMutableArray *protocolClasses = [NSMutableArray arrayWithArray:currentProtocolClasses];
[protocolClasses insertObject:[CustomURLProtocol class] atIndex:0];
sessionConfiguration.protocolClasses = protocolClasses;

【问题讨论】:

【参考方案1】:

如果文档这么说,那就是错误。请提交一份。逻辑实际上比那里描述的要简单得多。基本上操作系统的作用是这样的:

NSURLProtocol *protocol = nil;
for (Class protocolClass in sessionConfiguration.protocolClasses) 
    if ([protocolClass canInitWithRequest:request]) 
         protocol = [[protocolClass alloc] init];
    

if (!protocol) 
    fail

因此,只要您的协议列在首位,它们就会获得优先权。 (对于 NSURLConnection,文档的那一点也是错误的;总是先询问您注册的协议,然后再询问任何内置协议。)

如果您不需要处理标准协议,这样做就足够了:

sessionConfiguration.protocolClasses = @[[CustomURLProtocol class]];

您不能强制使用 URL 协议。当且仅当其 canInitWithRequest: 类方法为请求返回 YES 时,才会使用该协议。如果你想让不同的协议处理请求(例如,如果你想定义一个真正使用普通 https 请求的自定义 URL 方案),那么你通常会通过编写一个协议来重写 URL 并重新发出请求一个没有安装协议处理程序类的新会话。

或者,您可以在安装了处理程序的会话中重新发出请求,只要您以某种方式修改请求,以便您的协议处理程序知道在第二次看到请求时从其canInitWithRequest: 方法返回 NO时间。 (否则,您将获得无限递归。)

【讨论】:

嗨!您能否将示例代码更改为sessionConfiguration.protocolClasses = @[[CustomURLProtocol class]]; 以便更通用?谢谢 是的,当然。完成。 关于“数组将始终为空或为零”:我创建默认会话配置。它的 protocolClasses 数组已经包含 5 个 OS 协议:_NSURLHTTPProtocol_NSURLDataProtocol_NSURLFTPProtocol_NSURLFileProtocolNSAboutURLProtocol。我需要添加我的CustomURLProtocol。每当我的CustomURLProtocolcanInitWithRequest: 中返回 NO 时,应用程序必须回退到操作系统协议。 啊。我想我记错了。那我来编辑一下。

以上是关于如何确保使用了我的自定义 URL 协议?的主要内容,如果未能解决你的问题,请参考以下文章

如何确保让我的自定义 OidcUserService 被默认调用?

在 Internet Explorer 中使用同步可插入协议的自定义 url 协议的最大长度是多少?

具有父 url 参数的自定义 Django 管理站点

如何在我的自定义主题中包含自定义 js 文件?

OneSignal - 使用来自 url 的自定义图像从 android 应用发送通知

我应该在哪里将我的自定义域指向环境 URL 或 LoadBalancer?