RSWebView(UIWebView和WKWebView的混合框架,UIWebView自动切换到WKWebView)

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

支持情况说明:

  • UIWebView在iOS8及以后自动切换到WKWebView
  • 带有网页加载进度条
  • 支持设置html, url
  • 可注入js脚本
  • 可修改WebView请求的userAgent
  • 支持忽略ssl验证, 通过 addTrustedDomain 添加
  • 支持js交互 WebViewJavascriptBridge,有修改
  • 支持进度条 NJKWebViewProgress,有修改
  • 支持手势滑动后退,后退时显示上个页面截图(类似safari,wechat)
  • 支持从网页打开其他app,需要判断scheme是否允许
  • 处理 WKWebView问题 比如打开app store.
  • WebView加载本地资源(html,css,js,image...)

使用方法:

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; 页面开始加载时调用
- (void)webViewDidStartLoad:(UIWebView *)webView - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; 当内容开始返回时调用
- (void)webViewDidFinishLoad:(UIWebView *)webView - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; 页面加载完成之后调用
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(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

相关资料查询:

  • iOS开发之WKWebView简单使用

    进度条暂时都用了第三方的方法处理,其实有更好的,但是暂时没有处理。WKWebView有estimatedProgress的属性,然后配合UIProgressView设置出来的效果更佳好。

遇到的一些问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容