美文网首页
URLProtocol拦截

URLProtocol拦截

作者: Sh1mmer | 来源:发表于2019-06-10 09:52 被阅读0次

    一.创建NSURLProtocol延展类在里面实现注册监听WKWebview中的指定协议头的网络请求和解除监听WKWebview中的指定协议头的网络请求

    /**
     注册监听WKWebview中的指定协议头的网络请求
    
     @param scheme 协议头字符串
     */
    + (void)registerToWKWebviewWithScheme: (NSString *)scheme;
    
    /**
     解除监听WKWebview中的指定协议头的网络请求
    
     @param scheme 协议头字符串
     */
    + (void)unregisterToWKWebviewWithScheme: (NSString *)scheme;
    
    #import "NSUrlProtocol+Lemage.h"
    #import <WebKit/WebKit.h>
    
    @implementation NSURLProtocol (Lemage)
    
    FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
        static Class cls;
        if (!cls) {
            cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
        }
        return cls;
    }
    
    FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
        return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
    }
    
    FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
        return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
    }
    
    /**
     注册监听WKWebview中的指定协议头的网络请求
     
     @param protocol 协议头字符串
     */
    + (void)registerToWKWebviewWithScheme: (NSString *)scheme {
        Class cls = ContextControllerClass();
        SEL sel = RegisterSchemeSelector();
        if ([(id)cls respondsToSelector:sel]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [(id)cls performSelector:sel withObject:scheme];
    #pragma clang diagnostic pop
        }
    }
    
    /**
     解除监听WKWebview中的指定协议头的网络请求
     
     @param protocol 协议头字符串
     */
    + (void)unregisterToWKWebviewWithScheme: (NSString *)scheme {
        Class cls = ContextControllerClass();
        SEL sel = UnregisterSchemeSelector();
        if ([(id)cls respondsToSelector:sel]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [(id)cls performSelector:sel withObject:scheme];
    #pragma clang diagnostic pop
        }
    }
    

    接着在写我们自己的URLProtocol(继承NSURLProtocol)并且实现NSURLSessionDelegate协议

    + (BOOL)canInitWithRequest:(NSURLRequest *)request {
     
        if ([NSURLProtocol propertyForKey: @"你得标记" inRequest:request]) {
            // 处理后的request会打上标记,在这里判断一下,如果打过标记的request会放过,防止死循环
            return NO;
        }
        if ([request.URL.scheme caseInsensitiveCompare: @"我们需要处理的请求头"] == NSOrderedSame) {
            return YES;
        }
        return NO;
    }
    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
        return request;
    }
    
    - (void)startLoading{
        NSMutableURLRequest* request = self.request.mutableCopy;
    //在这是打上了印记,用来防止死循环
        [NSURLProtocol setProperty:@YES forKey: @"你得印记" inRequest:request];
        __block typeof(self) weakSelf = self;
        if ([request.URL.scheme caseInsensitiveCompare: @"需要处理的请求头"] == NSOrderedSame) {
            NSLog(@"--------------------------");
          //替换图片数据
            NSData *data = UIImageJPEGRepresentation([UIImage named:@"temp"],1.0f);
            NSURLResponse* response = [[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"image/png" expectedContentLength:data.length textEncodingName:nil];
           [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
           [self.client URLProtocol:self didLoadData:data];
           [self.client URLProtocolDidFinishLoading:self];
           
        }
    }
    //不写的话会崩溃
    - (void)stopLoading {
    }
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
        [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
        
        completionHandler(NSURLSessionResponseAllow);
    }
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
        [[self client] URLProtocol:self didLoadData:data];
    }
    

    在之后就是要在AppDelegate.h中注册我们自己定义的URLProtocol

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        [NSURLProtocol registerClass:[自定义的URLProtocol class]];
        [NSURLProtocol registerToWKWebviewWithScheme:@"要处理的请求头"];
    }
    

    相关文章

      网友评论

          本文标题:URLProtocol拦截

          本文链接:https://www.haomeiwen.com/subject/yklaxctx.html