简体   繁体   English

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

[英]How to make sure, that my custom URL protocol is used?

According to the documentation of NSURLSessionConfiguration::protocolClasses , there is no guaranty, that my custom url protocol will be used. 根据NSURLSessionConfiguration::protocolClasses的文档,没有保证将使用我的自定义url协议。 How can I ensure, that it is used whenever I set it to protocolClasses property? 我如何确保在将其设置为protocolClasses属性时使用它?

Prior to handling a request, an NSURLSession object searches the default protocols first and then checks your custom protocols until it finds one capable of handling the specified request. 在处理请求之前,NSURLSession对象首先搜索默认协议,然后检查您的自定义协议,直到找到能够处理指定请求的协议为止。 It uses the protocol whose canInitWithRequest: class method returns YES, indicating that the class is capable of handling the specified request. 它使用canInitWithRequest:类方法返回YES的协议,表明该类能够处理指定的请求。

I can't set an array with single URL protocol, because it has logic for canInitWithRequest: method and might not handle all request. 我无法使用单个URL协议设置数组,因为它具有canInitWithRequest:方法的逻辑,并且可能无法处理所有请求。

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

If the docs say that, it's a bug. 如果文档这么说,那是一个错误。 Please file one. 请提出一个。 The logic is actually much simpler than what is described there. 逻辑实际上比那里描述的要简单得多。 Basically what the OS does is this: 基本上,操作系统是这样的:

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

So as long as your protocols are listed first, they'll get priority. 因此,只要您的协议列在第一位,它们就会获得优先权。 (For NSURLConnection, that bit of the doc was also wrong; your registered protocols are always asked first, before any of the built-in protocols.) (对于NSURLConnection,该文档的那部分内容也是错误的;始终会在所有内置协议之前首先询问您注册的协议。)

If you don't need to handle standard protocols, it is sufficient for you to do this: 如果您不需要处理标准协议,则只需执行以下操作:

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

You cannot force a URL protocol to be used. 您不能强制使用URL协议。 The protocol will be used if and only if its canInitWithRequest: class method returns YES for the request. 仅当其canInitWithRequest:类方法对该请求返回YES时,才会使用该协议。 If you want to make a different protocol handle a request (eg if you want to define a custom URL scheme that really uses a normal https request), then you would typically do so by writing a protocol that rewrites the URL and reissues the request in a new session that does not have your protocol handler class installed. 如果您想让其他协议处理请求(例如,如果您想定义一个真正使用普通https请求的自定义URL方案),则通常可以通过编写一个协议来重写URL并在其中重新发出请求来实现。一个没有安装协议处理程序类的新会话。

Alternatively, you can reissue the request in a session that does have your handler installed so long as you modify the request in some way so your protocol handler knows to return NO from its canInitWithRequest: method when it sees the request a second time. 或者,您可以在确实安装了处理程序的会话中重新发出请求,只要您以某种方式修改了请求,以便协议处理程序在第二次看到请求时便知道其canInitWithRequest:方法返回NO。 (Otherwise, you'll get infinite recursion.) (否则,您将获得无限递归。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM