Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSURL协议未获取完整的NSURL请求_Objective C_Nsurlconnection_Nsurlprotocol - Fatal编程技术网

Objective c NSURL协议未获取完整的NSURL请求

Objective c NSURL协议未获取完整的NSURL请求,objective-c,nsurlconnection,nsurlprotocol,Objective C,Nsurlconnection,Nsurlprotocol,问题:我有NSURLProtocol的子类,但由+canonicalRequestForRequest:返回的NSURLRequest或由-connection:willSendRequest:redirectResponse:返回的请求从未传递到我的URL协议实例 详细信息:在NSURLProtocol的子类中,我实现了方法+canonicalRequestForRequest:向请求添加HTTP头。头添加成功,但在我的URL协议上调用-startLoading时,self.request不包

问题:我有NSURLProtocol的子类,但由+canonicalRequestForRequest:返回的NSURLRequest或由-connection:willSendRequest:redirectResponse:返回的请求从未传递到我的URL协议实例

详细信息:在NSURLProtocol的子类中,我实现了方法+canonicalRequestForRequest:向请求添加HTTP头。头添加成功,但在我的URL协议上调用-startLoading时,self.request不包括该头

此外,当对NSURLConnection的委托调用connection:willSendRequest:redirectResponse:时,该方法返回的任何请求也不会到达我的URL协议实例

我认为问题在于initWithRequest:cachedResponse:client:在调用+canonicalRequestForRequest:或connection:willSendRequest:redirectResponse:之前被调用,并且来自这两个方法的结果请求在alloc/init之后永远不会传递到我的URL协议实例

这是苹果URL加载系统中的一个错误吗?有解决办法吗?我做错什么了吗

更新日期:2014年4月6日 下面是一些示例代码。我设置了两个头:一个在-[APViewController连接:willSendRequest:redirectResponse:]中调用X-WillSendRequestTest,另一个在+[APURLProtocol canonicalRequestForRequest:]中。通过在-[APURLProtocol-startLoading]内调用self.request获取的NSURLRequest中没有一个

APViewController.m是NSURL协议的代表

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse {
    NSLog(@"Will send request: %@", request);

    NSMutableURLRequest *newRequest = [request mutableCopy];

    // This header will not be in self.request when fetched within the -[APURLProtocol start loading] method.
    [newRequest setValue:@"12345" forHTTPHeaderField:@"X-WillSendRequestTest"];

    NSLog(@"New request: %@", newRequest);

    return newRequest;
}
APURLProtocol.m


首先一件事:为什么要在+canonicalRequestForRequest:中添加头?我不会这么做的。使用这种方法很容易引入bug。请查看有关此方法的文档以及canonical的含义。没有说这是问题所在,但是您是否尝试过在这个方法中返回相同的请求,并在-starting方法中添加您的头?方法+canonicalRequestForRequest:是您应该规范化请求的地方。从文档来看:定义“规范”的含义取决于每个具体的协议实现。协议应该保证相同的输入请求总是产生相同的规范形式。事实上,在苹果的iOS示例CustomHTTPProtocol中,他们通过在该方法中添加Accept、Accept Encoding和Accept Language头来规范化请求。是的,+canonicalRequestForRequest:,这就是我提到它的原因。我之所以这么说,是因为根据实现,您可能会通过实际创建一个不规范的请求来引入bug。这就是为什么我不确定这是问题的原因,但它可能是。我看过苹果的例子,但不久前我也看到过这个例子,它工作得很好,它以惊人的加载方法设置了标题。因此,我试图帮助减少错误的可能性。你有没有试过将它们放在令人震惊的加载方法中?如果不查看代码,就很难调查错误是什么,但至少如果我们排除一些可能性,就可以更容易地发现您可能存在的任何错误。@rocir我添加了一些示例代码。是的,我当前在+canonicalRequestForRequest:中添加的头可以移动到-startLoading。但是,我关心的是,为什么方法+canonicalRequestForRequest:或连接:willSendRequest:redirectResponse:NSURLConnectionDataDelegate协议返回的NSURLRequest被完全忽略,而没有转发到处理连接的NSURLProtocol子类?
@interface APURLProtocol () <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
// Private properties
@property (nonatomic, strong) NSURLConnection *connection;
@end




@implementation APURLProtocol

#pragma mark -
#pragma mark Init methods

- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    if ((self = [super initWithRequest:request cachedResponse:cachedResponse client:client])) {

    }

    return self;
}



#pragma mark -
#pragma mark dealloc

- (void)dealloc {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    [_connection cancel];
}



#pragma mark -
#pragma mark Inherited class methods

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    NSLog(@"%@ %@", NSStringFromSelector(_cmd), request);

    id requestIsHandled = [self propertyForKey:kAPURLProtocolHandledRequest inRequest:request];

    if (requestIsHandled == nil
            && ([request.URL.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame
                    || [request.URL.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame
                    || [request.URL.scheme caseInsensitiveCompare:@"ftp"] == NSOrderedSame)) {
                NSLog(@"YES");
                return YES;
            }

    NSLog(@"NO");
    return NO;
}


+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    NSMutableURLRequest *newRequest = [request mutableCopy];
    // This header will not be in self.request when fetched within the -[APURLProtocol start loading] method.
    [newRequest setValue:@"12345" forHTTPHeaderField:@"X-CanonicalRequestTest"];

    return newRequest;
}


+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)aRequest toRequest:(NSURLRequest *)bRequest {
    NSLog(@"Request is cache equivalent:");
    NSLog(@"Request 1: %@", aRequest);
    NSLog(@"Request 2: %@", bRequest);

    return YES;
}



#pragma mark -
#pragma mark Inherited instance methods

- (void)startLoading {
    NSLog(@"%@. Request: %@", NSStringFromSelector(_cmd), self.request);

    NSMutableURLRequest *newRequest = [[self request] mutableCopy];
    [[self class] setProperty:@"" forKey:kAPURLProtocolHandledRequest inRequest:newRequest];

    [self.connection cancel];

    self.connection = [[NSURLConnection alloc] initWithRequest:newRequest
                                                                                                        delegate:self
                                                                                        startImmediately:YES];
}
@end
@implementation NSURLRequest (test)

- (NSString *)description {
    NSString *dataString = [[NSString alloc] initWithData:self.HTTPBody encoding:NSUTF8StringEncoding];

    return [NSString stringWithFormat:@"%@: %p {URL: %@, Method: %@, Headers: %@, Data: %@",
                    NSStringFromClass([self class]), self, self.URL, self.HTTPMethod, [self allHTTPHeaderFields], dataString];
}

@end