iOS BlogRason的iOS开发进阶专题iOS

RSWebView(UIWebView和WKWebView的混合

2016-04-24  本文已影响3106人  RasonWu

UIWebView和WKWebView的混合框架,UIWebView自动切换到WKWebView。只要直接把UIWebView换成RSWebView即可,如果UIWebView还有其它特殊的处理,也需要实现WKWebView对应的代理。iOS8以后,苹果推出了新框架Wekkit,提供了替换UIWebView的组件WKWebView。速度更快了,占用内存少了,转为WKWebView是必然的趋势。RSWebView当UIWebView直接使用。

支持情况说明:

使用方法:

pod加入以下部分:

pod 'RSWebView', :git => 'git@github.com:air1120/RSWebView.git'

把UIWebView换成RSWebView即可,支持UIWebView的所有方法和代理不受影响。可以把RSWebView当做UIWebView使用。注意如果在使用RSWebView的ViewController中,如果需要实现了UIWebView的代理方法,也要对应实现WKWebView的代理方法。

扩展功能:

修改userAgent
//使用之后,需要通过[RSWebView setUserAgent:nil];来恢复
+(void)setUserAgent:(NSString *)userAgent;
对于POST或GET的扩展请求,headers是字典类型,body是字典或字符串形式,设置即发送请求。

设置一:

_webView.webSource = [[RSWebSource alloc]initWithUrl:@"http://www.baidu.com" method:@"GET" headers:nil body:nil];

设置二:

_webView.webSource = [[RSWebSource alloc]initWithHtml:@"<html><div>测试</div></html>" baseURL:@""];
读取本地文件:
-(void)loadLocalFile:(NSString *)fileName baseURL:(NSString *)baseURL;
-(void)loadLocalFile:(NSString *)fileName;
WebViewJavascriptBridge的js交互部分:
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler;
- (void)callHandler:(NSString *)handlerName;
- (void)callHandler:(NSString *)handlerName data:(id)data;
- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
添加忽略ssl验证(iOS https请求为什么要忽略证书
[BBWebViewSSLProtocol addTrustedDomain:@"js.com"];
限制外部应用打开
//包括获取本地资源,所以file必须要加上
    webView.trustedScheme = @[@"file",@"mqq"];

trustedScheme不设置,则不会限制。

存在的问题:

stringByEvaluatingJavaScriptFromString的方法执行alert, comfirm,prompt等关于界面的操作并不能直接返回对应的返回值。由于WKWebView的evaluateJavaScript是异步的,但改为同步执行的过程中出问题,目前仍未解决。其它部分经过测试并无问题。当然您可以选择使用evaluateJavaScript的方法代替stringByEvaluatingJavaScriptFromString的执行是完全没问题的。

UIWebView代理对应表

UIWebView代理 |WKWebView代理 |说明
------------------------|---------------
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; |- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; |页面开始加载时调用

实现思路及遇到的问题(下面部分可不看,总结用)

一些处理思路:
从实际WebView的代理给WebViewJavascriptBridge,WebViewJavascriptBridge回调NJKWebViewProgress的代理方法,NJKWebViewProgress再回调RWWebView的方法,RWWebView再回调对应Controller的方法。

WebViewJavascriptBridge的完全说明:

1.由于WKWebViewJavascriptBridge会截获WKNavigationDelegate的所有响应,所以需要添加事件转发。
2.而事件转发需要提前知道delegate有没有实现对应的方法。所以需要先设置delegate。
3.其实也可以直接重写对应的方法,不过为了尽量保持原有的代理方法,采用了1,2的做法。

WebViewJavascriptBridge的实现js交互的原理:

总结一下:js这边 先把方法名字、参数、处理方法保存成一个字典在转成json字符串,在通过UIWebview调用js中某个方法把这个json字符串传到Native中 去(不是通过url传的,这样太low了),同时把这个处理的方法以key-value形式放到一个js的字典中。UIWebView在收到这个json之后,进行数据处理、还有js的回掉的处理方法(就是那个callbackId)处理完成后也会拼成一个key-value字典通过调用js传回去(可以直接调用js)。js在接到这个json后,根据responseId读取responseCallbacks中处理方法进行处理Native code返回的数据。

总结:native将方法名、参数、回到的id放到一个对象中传给js。js根据方法名字调用相应方法,之后将返回数据和responseId拼装,最后通过src 重定向到UIWebview 的delegate。native得到数据后根据responseId调用事先装入_responseCallbacks的block,动态读取调用,从而完成交互。

兼容情况说明:

  1. 处理 WKWebView不能打开URL Scheme and App Store的问题
  2. webView支持缩放(scalesPageToFit)

一个关于系统版本的技巧,代码如下:

#if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1)
#define supportsWKWebKit
#endif

#if defined(supportsWKWebKit )
//这里写类相关的东西
#endif

相关资料查询:

遇到的一些问题

上一篇下一篇

猜你喜欢

热点阅读