問題: NSURLProtocol のサブクラスがありますが、NSURLRequest
返された+canonicalRequestForRequest:
または返された要求-connection:willSendRequest:redirectResponse:
が URL プロトコル インスタンスに渡されません。
詳細: のサブクラスでリクエストに HTTP ヘッダーを追加するNSURLProtocol
メソッドを実装し+canonicalRequestForRequest:
ヘッダーは正常に追加されましたが-startLoading
、URL プロトコルで呼び出されself.request
、そのヘッダーが含まれていません。
さらに、connection:willSendRequest:redirectResponse:
のデリゲートで が呼び出された場合NSURLConnection
、そのメソッドによって返された要求が何であれ、URL プロトコル インスタンスにも到達しません。
initWithRequest:cachedResponse:client:
問題は、呼び出される前+canonicalRequestForRequest:
または呼び出されることにあると思います。これらの 2 つのメソッドからの結果のリクエストは、 /connection:willSendRequest:redirectResponse:
になった後に URL プロトコル インスタンスに渡されません。alloc
init
これは Apple の URL 読み込みシステムのバグですか? 回避策はありますか? 私は何か間違ったことをしていますか?
2014 年 4 月 6 日の更新
ここにいくつかのサンプルコードがあります。2 つのヘッダーを設定しました。1 つは-[APViewController connection:willSendRequest:redirectResponse:]
呼び出されX-WillSendRequestTest
、もう 1 つは+[APURLProtocol canonicalRequestForRequest:]
. どちらもwithinNSURLRequest
を呼び出してフェッチされません。self.request
-[APURLProtocol startLoading]
APViewController.m (NSURLProtocol のデリゲート)
- (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
@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
NSURLRequest+test.m (NSURLRequestの記述を拡張するカテゴリ)
警告: 自宅でこれを行わないでください。カテゴリを使用してメソッドまたはプロパティをオーバーライドしないでください。これは、迅速なデバッグのみを目的としています。
@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