NSURLProtocol处理WKWebView的http和https的请求

iOS8以后,苹果推出了Webkit框架,使用WKWebView替换了UIWebView,可以是网页的速度更快,内存更少。但是WKWebView的http和https请求,不能被URL Loading System处理,在做的过程中,遇到了问题并做记录。

1.不能截获的原因。

    其实WKWebView在一开始的时候,会调用NSURLProtocol的入口方法canInitWithRequest,只是直接返回了NO,就没有然后了。由此看出苹果不希望开发者使用NSURLProtocol。所以在后边的实现的时候,就需要混淆一下,避免苹果静态代码检查的时候通不过审核。

 

 

2.实现MyURLProtocol继承于NSURLProtocol

#import 

NS_ASSUME_NONNULL_BEGIN

@interface MyURLProtocol : NSURLProtocol
+ (void)registerScheme;
@end

NS_ASSUME_NONNULL_END

2.1  要把http和https交给NSURLProtocol处理

      [[WKBrowsingContextController class]  performSelector:NSSelectorFromString(@"registerSchemeForCustomProtocol:")  withObject:@"http"];

    为了避免静态代码检查审核不通过,需要做一下处理

   

static NSString* const BFHybridBTWKKey = @"blackfish";
static NSString* const BFHybridBTWKCls = @"T0M7aWh1bmRqXztoZW1jc28/Z2ZtaWhqZ2Bu";
static NSString* const BFHybridBTWKSel = @"al1gYGxyYG1PW2BeZF5Eam0/bWttZmZObWpwZ1toYzM=";



#pragma mark - public

+ (void)registerScheme {
    Class cls = NSClassFromString([self decodeString:BFHybridBTWKCls key:BFHybridBTWKKey]);
    SEL sel = NSSelectorFromString([self decodeString:BFHybridBTWKSel key:BFHybridBTWKKey]);
    if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        // 把 http 和 https 请求交给 NSURLProtocol 处理
        [(id)cls performSelector:sel withObject:@“http”];
        [(id)cls performSelector:sel withObject:@"https"];
#pragma clang diagnostic pop
    }
}



//base64解码

/**
 这个类是为了通过苹果的静态检查

 @param string 按照算法加密之后的字符串 并且base64加密
 @param key 关键字 用来计算隐藏的类
 @return 目的类名和方法名
 */
+ (NSString *)decodeString:(NSString *)string key:(NSString *)key
{
    NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters];
    NSString *deString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    NSMutableString *mutString = [NSMutableString new];
    for (int i = 0;i < deString.length;i++) {
        int strChar = [deString characterAtIndex:i];
        int keyChar = [key characterAtIndex:(i % key.length)];
        int charactor = strChar + (keyChar % 10);
        [mutString appendString:[NSString stringWithFormat:@"%c",charactor]];
    }
    
    return mutString;
}

2.2 为了避免循环处理 需要标注一下已经处理的请求

static NSString* const BFHybridFilteredKey = @"BFHybridFilteredKey";

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    NSString *scheme = [[request URL] scheme];
    
    //正常请求不做处理
    if ( ([scheme caseInsensitiveCompare:@"https"] == NSOrderedSame ||
          [scheme caseInsensitiveCompare:@"http"] == NSOrderedSame)) {
        return [NSURLProtocol propertyForKey:BFHybridFilteredKey inRequest:request] == nil;
    }
    return NO;
}

- (void)startLoading {
    
    NSMutableURLRequest* request = self.request.mutableCopy;
    [NSURLProtocol setProperty:@YES forKey:BFHybridFilteredKey inRequest:request];
    
        //发送重定向请求
     NSURLSessionConfiguration *configure = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    self.session  = [NSURLSession sessionWithConfiguration:configure delegate:self delegateQueue:queue];
     self.task = [self.session dataTaskWithRequest:request];
        [self.task resume];

}

2.3  在程序启动的时候,就注册NSURLProtocol的子类

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [MyURLProtocol registerScheme];
    [NSURLProtocol registerClass:[MyURLProtocol class]];
    return YES;
}

demo源码

你可能感兴趣的:(iOS网络总结)