ios wkweb设置图片_iOS WKWebView (NSURLProtocol)拦截js、css,图片资源

本文介绍了如何在iOS中使用WKWebView结合NSURLProtocol拦截并处理WKWebView内的js、css和图片资源请求。通过反射机制,实现了WKWebView对http和https协议的注册,使得所有请求能够遵循NSURLProtocol。示例代码展示了如何重定向请求和加载本地离线文件。
摘要由CSDN通过智能技术生成

项目地址github:HybirdWKWebVIew

HybridNSURLProtocol

一个基于WKWebView的hybirde的容器。能拦截所有WKWKWebView的的css,js,png等网络请求的demo

NSURLProtocol 子类,就可以对 app 内所有的网络请求进行:

[NSURLProtocol registerClass:[HybridNSURLProtocol class]]

可是在 WKWebView 中的请求却完全不遵从这一规则,只是象征性+ (BOOL) canInitWithRequest:(NSURLRequest *)request 方法,之后的整个请求流程似乎就与 NSURLProtocol 完全无关了。

使我WKWebView 的一度认为请求不遵守NSURLProtocol协议,所以不走 NSURLProtocol。这个也是很苦扰我的问题。导致我们hybird的容器1.0也是是用UIWebVIew实现的。

但在苹果放在gittub的CustomHTTPProtocol,明显感觉到WKWebview的也是遵守NSURLProtocol,要不也不会走+ (BOOL)canInitWithRequest:(NSURLRequest *)request;后来一个每天看博客和gittub的习惯帮助了我,找到一个大神的不久前开源库。

使用了WKBrowsingContextController和registerSchemeForCustomProtocol。 通过反射的方式拿到了私有的 class/selector。通过kvc取到browsingContextController。通过把注册把 http 和 https 请求交给 NSURLProtocol 处理。

[NSURLProtocol wk_registerScheme:@"http"];

[NSURLProtocol wk_registerScheme:@"https"];

下面直接上源代码吧

//FOUNDATION_STATIC_INLINE 属于属于runtime范畴,你的.m文件需要频繁调用一个函数,可以用static inline来声明。在SDWebImage读取内存的缓存也用到这个声明。

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:");

}

@implementation NSURLProtocol (WebKitSupport)

+ (void)wk_registerScheme:(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

}

}

+ (void)wk_unregisterScheme:(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

}

}

注册后,客户端所有请求走+ (BOOL)canInitWithRequest:(NSURLRequest *)request。下面是打印的请求的log

+ (BOOL)canInitWithRequest:(NSURLRequest *)request

{

NSLog(@"request.URL.absoluteString = %@",request.URL.absoluteString);

NSString *scheme = [[request URL] scheme];

if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||

[scheme caseInsensitiveCompare:@"https"] == NSOrderedSame ))

{

//看看是否已经处理过了,防止无限循环

if ([NSURLProtocol propertyForKey:KHybridNSURLProtocolHKey inRequest:request])

return NO;

return YES;

}

return NO;

}

Aaron Swartz

request的重写定向,request的重写定向,替换百度知道的log

+ (BOOL)canInitWithRequest:(NSURLRequest *)request

{

NSLog(@"request.URL.absoluteString = %@",request.URL.absoluteString);

NSString *scheme = [[request URL] scheme];

if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||

[scheme caseInsensitiveCompare:@"https"] == NSOrderedSame ))

{

//看看是否已经处理过了,防止无限循环

if ([NSURLProtocol propertyForKey:KHybridNSURLProtocolHKey inRequest:request])

return NO;

return YES;

}

return NO;

}

这里最好加上缓存判断,加载本地离线文件, 这个直接简单的例子。

- (void)startLoading

{

NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];

//给我们处理过的请求设置一个标识符, 防止无限循环,

[NSURLProtocol setProperty:@YES forKey:KHybridNSURLProtocolHKey inRequest:mutableReqeust];

//这里最好加上缓存判断,加载本地离线文件, 这个直接简单的例子。

if ([mutableReqeust.URL.absoluteString isEqualToString:sourIconUrl])

{

NSData* data = UIImagePNGRepresentation([UIImage imageNamed:@"medlinker"]);

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];

}

else

{

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

self.task = [session dataTaskWithRequest:self.request];

[self.task resume];

}

}

下面是代码效果图

WechatIMG1.png

WechatIMG2.jpeg

项目地址:

github:HybirdWKWebVIew,对您有帮助,欢迎star。

有问题反馈

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

github:LiuShuoyu

接受启发的作者的github

github:Yeatse CC

苹果开发者文档:apple

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值