为了解决 UIWebView 加载速度慢、占用内存大的问题,苹果在 iOS8.0 之后推出了 WKWebView 以替代之,在使用 WKWebView 前先引入 <WebKit/WebKit.h>
框架。
WKWebView 属性
WKWebView 在原有基础上额外添加了几个属性如下:
// 浏览器配置;
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
// 历史访问列表;
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
// 网页加载进度;
@property (nonatomic, readonly) double estimatedProgress;
1
2
3
4
5
6
2
3
4
5
6
WKWebView 代理
WKWebView 可以同时设置 WKNavigationDelegate 和 WKUIDelegate 两个代理,代理方法也有所改变如下:
#pragma mark - WKNavigationDelegate
// 在发送请求前的操作;
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {}
// 在收到响应后的操作;
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {}
// 在页面重指向时的操作;
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {}
// 页面准备加载;
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {}
// 页面开始加载;
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {}
// 页面完成加载;
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {}
// 页面加载失败;
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {}
// 页面跳转失败;
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {}
#pragma mark - WKUIDelegate
// 创建新的WebView;
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {}
// 拦截警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {}
// 拦截确认框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {}
// 拦截提示框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
此外 WKWebView 新增了根据文件加载 WebView 的方法:
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);
1
WebViewJavascriptBridge 实现交互
在项目中使用 WebViewJavascriptBridge 先添加 OC 代码如下:
WKWebView* webView = [[NSClassFromString(@"WKWebView") alloc] initWithFrame:self.view.bounds];
webView.navigationDelegate = self;
[self.view addSubview:webView];
// 设置允许桥接
[WKWebViewJavascriptBridge enableLogging];
// 初始化桥接对象并设置代理
_bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
[_bridge setWebViewDelegate:self];
// 注册函数testObjcCallback引用JS
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"testObjcCallback called: %@", data);
responseCallback(@"Response from testObjcCallback");
}];
// 回调函数testJavascriptHandler供JS引用
[_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];
[self renderButtons:webView];
[self loadExamplePage:webView];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
然后在 HTML 文件中添加 js
代码如下:
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
window.WVJBCallbacks = [callback]
var WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
document.documentElement.appendChild(WVJBIframe)
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
OC 引用 JS
OC 中注册函数:
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"testObjcCallback called: %@", data);
responseCallback(@"Response from testObjcCallback");
}];
1
2
3
4
2
3
4
JS 中实现回调函数:
setupWebViewJavascriptBridge(function(bridge) {
bridge.callHandler('testObjcCallback', { foo: 'bar' }, function(response) {
// 该函数为js中声明的函数;
log('JS got response', response)
})
})
1
2
3
4
5
6
2
3
4
5
6
JS 引用 OC
JS 中注册函数:
bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
log('ObjC called testJavascriptHandler with', data)
var responseData = { 'Javascript Says': 'Right back atcha!' }
log('JS responding with', responseData)
responseCallback(responseData)
})
1
2
3
4
5
6
2
3
4
5
6
OC 中实现回调并传值:
[_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];
1
以上就是 WebViewJavascriptBridge 与 WKWebView 的基本交互使用。