我一直在编写一个Mac应用程序来检查每个HTTP请求,因此我使用WebView加载请求.
我正在尝试通过WebResourceLoadDelegate方法获取资源的内容:
- (void)webView:(WebView *)sender resource:(id)identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource
这似乎不起作用.
我也在查看[dataSource数据],但这只是给了我请求的HTML而不是资源项的数据.
解决方法
是的,这应该有效,似乎曾经有过.您可以通过实现自定义NSURLProtocol来解决它.
首先,您需要弄清楚您有兴趣拦截哪些请求(或者所有这些请求,无论如何).我在我的WebResourceLoadDelegate中执行此操作.如果我关心请求,我将其替换为我自己的请求,将自己附加为属性.我稍后会在NSURLProtocol中使用该属性.
- (NSURLRequest*) webView:(WebView*)sender resource:(id)identifier willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse fromDataSource:(WebDataSource*)dataSource { // Am I interested in this request? if (/* figure out if you want it or not */) { NSMutableURLRequest* newRequest = [[request mutableCopy] autorelease]; [NSURLProtocol setProperty:self forKey:@"MyApp" inRequest:newRequest]; return newRequest; } else { // Not interested,let it go through normally return request; } }
我的NSURLProtocol看起来像这样.
@interface MyURLProtocol : NSURLProtocol { id _delegate; NSURLConnection* _connection; NSMutableData* _data; } @end
在我的NSURLProtocol子类中,我可以使用附加属性来查看是否应该拦截响应.
+ (BOOL) canInitWithRequest:(NSURLRequest*)request { id delegate = [NSURLProtocol propertyForKey:@"MyApp" inRequest:request]; return (delegate != nil); }
在initWithRequest中,我将委托移动到我的NSURLProtocol实例中,并从请求中删除该属性.当我实际尝试加载此请求时,这会阻止无限循环.
- (id) initWithRequest:(NSURLRequest*)theRequest cachedResponse:(NSCachedURLResponse*)cachedResponse client:(id<NSURLProtocolClient>)client { // Move the delegate from the request to this instance NSMutableURLRequest* req = (NSMutableURLRequest*)theRequest; _delegate = [NSURLProtocol propertyForKey:@"MyApp" inRequest:req]; [NSURLProtocol removePropertyForKey:@"MyApp" inRequest:req]; // Complete my setup self = [super initWithRequest:req cachedResponse:cachedResponse client:client]; if (self) { _data = [[NSMutableData data] retain]; } return self; }
剩下的就是库存URL加载的东西.
- (void) startLoading { _connection = [[NSURLConnection connectionWithRequest:[self request] delegate:self] retain]; } - (void) stopLoading { [_connection cancel]; } - (void)connection:(NSURLConnection*)conn didReceiveResponse:(NSURLResponse*)response { [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:[[self request] cachePolicy]]; [_data setLength:0]; } - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { [[self client] URLProtocol:self didLoadData:data]; [_data appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection*)conn { [[self client] URLProtocolDidFinishLoading:self]; // Forward the response to your delegate however you like if (_delegate && [_delegate respondsToSelector:@selector(...)]) { [_delegate ... withRequest:[self request] withData:_data]; } } - (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)theRequest redirectResponse:(NSURLResponse*)redirectResponse { return theRequest; } - (void)connection:(NSURLConnection*)conn didFailWithError:(NSError*)error { [[self client] URLProtocol:self didFailWithError:error]; }