URLProtocol拦截

2019-06-10  本文已影响0人  Sh1mmer

一.创建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:@"要处理的请求头"];
}
上一篇下一篇

猜你喜欢

热点阅读