webkitview tutorial open new example iphone ios uiwebview nsurlrequest

iphone - tutorial - webkitview swift 4



Enviar encabezados personalizados con UIWebView loadRequest (4)

Aquí hay una implementación completa usando NSURLProticol. Puede colocar este código en cualquier lugar que desee (ei propio o agregarlo a un archivo fuente existente) y debería funcionar. Los dos métodos clave para personalizar son canInitWithRequest: y canonicalRequestForRequest:

static NSString * const NSURLProtocolHandledKey = @"NSURLProtocolHandledKey"; @interface WTCURLProtocol : NSURLProtocol<NSURLSessionDelegate> @property (atomic,strong,readwrite) NSURLSessionDataTask *task; @property (nonatomic,strong) NSURLSession *session; @end @implementation WTCURLProtocol +(void)load { [NSURLProtocol registerClass:self]; } + (BOOL)canInitWithRequest:(NSURLRequest *)request { // customize here by returning true for URLs that you want to handle return [request.URL.absoluteString hasPrefix:WEB_BASE_URL]; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { NSMutableURLRequest *newRequest = request.mutableCopy; [NSURLProtocol setProperty:@YES forKey:NSURLProtocolHandledKey inRequest:newRequest]; // customize here by setting your custom headers [newRequest setValue:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ" forHTTPHeaderField:@"API-TOKEN"]; return newRequest; } - (void)startLoading { NSURLSessionConfiguration *configure = [NSURLSessionConfiguration defaultSessionConfiguration]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; self.session = [NSURLSession sessionWithConfiguration:configure delegate:self delegateQueue:queue]; self.task = [self.session dataTaskWithRequest:self.request]; [self.task resume]; } - (void)stopLoading { [self.session invalidateAndCancel]; self.session = nil; } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error != nil) { [self.client URLProtocol:self didFailWithError:error]; }else { [self.client URLProtocolDidFinishLoading:self]; } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; completionHandler(NSURLSessionResponseAllow); } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { [self.client URLProtocol:self didLoadData:data]; } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * _Nullable))completionHandler { completionHandler(proposedResponse); } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler { NSMutableURLRequest *redirectRequest = [newRequest mutableCopy]; [[self class] removePropertyForKey:NSURLProtocolHandledKey inRequest:redirectRequest]; [[self client] URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:response]; [self.task cancel]; [[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]]; } - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *card = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); } } @end

Quiero poder enviar algunos encabezados adicionales con mi método UIWebView loadRequest .

Yo he tratado:

NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.reliply.org/tools/requestheaders.php"]]; [req addValue:@"hello" forHTTPHeaderField:@"aHeader"]; [self.theWebView loadRequest:req];

También he intentado subclasificar UIWebView e interceptar - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType método de tipo de - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType .

En ese método tenía un bloque de código que se veía así:

NSMutableURLRequest *newRequest = [request mutableCopy]; for(NSString *key in [customHeaders allKeys]) { [newRequest setValue:[customHeaders valueForKey:key] forHTTPHeaderField:key]; } [self loadRequest:newRequest];

Pero por alguna razón desconocida, esto causaba que la vista web no cargara nada (marco en blanco) y NSURLErrorCancelled (-999) mensaje de error NSURLErrorCancelled (-999) (todas las correcciones conocidas no lo solucionan para mí).

Así que estoy en una pérdida en cuanto a qué hacer. ¿Cómo puedo enviar un encabezado personalizado junto con una solicitud UIWebView ?

¡Muchas gracias!


Descubrí que esta era la forma de agregar encabezados a mi solicitud UIWebView: anular este método de delegado:

- (BOOL) webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType) navigationType

Con este código:

BOOL headerIsPresent = [[request allHTTPHeaderFields] objectForKey:@"my custom header"]!=nil; if(headerIsPresent) return YES; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_main_queue(), ^{ NSURL *url = [request URL]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; // set the new headers for(NSString *key in [self.customHeaders allKeys]){ [request addValue:[self.customHeaders objectForKey:key] forHTTPHeaderField:key]; } // reload the request [self loadRequest:request]; }); }); return NO;


Encuentro otra forma, Puedo usar NSURLProtocol .

-(BOOL)webView:(IMYVKWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSMutableDictionary* mapObject = [NSMutableDictionary dictionary]; mapObject[@"headers"] = request.allHTTPHeaderFields; mapObject[@"navigationType"] = @(navigationType); [webViewRequestMap setObject:mapObject forKey:request.URL.absoluteString]; return YES; }

webViewRequestMap es Static NSMutableDictionary *

en su código de NSURLProtocol personalizado:

@interface IMYCustomURLProtocol : NSURLProtocol @end @implementation IMYCustomURLProtocol +(void)load { [NSURLProtocol registerClass:self]; } + (BOOL)canInitWithRequest:(NSURLRequest *)request { NSString* urlString = request.URL.absoluteString; NSDictionary* dictionary = webViewReuqestMap[urlString]; if (dictionary) { [webViewRequestMap removeObjectForKey:urlString]; if ([request isKindOfClass:[NSMutableURLRequest class]]) { [(id)request setValue:@"HAHA" forHTTPHeaderField:@"MeiYou Co.,Ltd"]; } } return NO; } @end


La respuesta de Thomas no funcionará para (la mayoría de las) páginas web con múltiples iFrames. La solución cargará una solicitud de iFrame sobre el UIWebView completo. Por ejemplo, en caso de que llame a loadRequest para un advt de Google. (que es en algún pequeño iFrame) la advt. se carga en todo el UIWebView y nada más.