iOS8之后,苹果推出了WebKit框架,相较于UIWebview,WKWebView在性能、功能方面都有了大幅度地提高,当然多多少少也会遇到一些在UIWebview中遇不到的麻烦事,这两天在项目中使用WKWebView时候遇到了一些问题,记录一下以备查阅。

JavaScript 调用alert 的问题

JS中调用alert,会在WKUIDelegate协议中拦截(即不弹出),需要实现相关代理方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//JavaScript调用alert方法后回调的方法 message中为alert提示的信息 必须要在其中调用completionHandler()
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}])];
[self presentViewController:alert animated:YES completion:nil];
}
//JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
NSLog(@"%@",message);
completionHandler(YES);
}
//JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
NSLog(@"%@",prompt);
completionHandler(@"这是我输入的内容");
}

JavaScript 调用javascript:window.open() 的问题

下面这个代理方法会拦截到window.open()事件,不能打开新窗口,即点了某一个按钮没反应(实际上是事件被拦截,打不开新窗口)

stackoverflow上的相似问题

1
2
3
4
5
6
7
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}

JavaScript 调 Native 相关问题

1.注册

1
2
WKUserContentController *userController = [[WKUserContentController alloc]init]; [userController addScriptMessageHandler:self name:@"test"];
configuration.userContentController = userController;

2.回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
/*
//传递的消息主体
@property (nonatomic, readonly, copy) id body;
//传递消息的WebView
@property (nullable, nonatomic, readonly, weak) WKWebView *webView;
//传递消息的WebView当前页面对象
@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;
//消息名称
@property (nonatomic, readonly, copy) NSString *name;
*/
if ([message.name isEqualToString:@"test"]) {
//do something
}
}

3.JS端写

  • 注意的点:
    • messageHandlers 后面所跟的name必须和iOS端保持一致。
    • postMessage()必须带有内容,没值填null或者空字符串都行,否则iOS端无法接收到回调。(别问我怎么知道的)
1
window.webkit.messageHandlers.test.postMessage('ios')

WKWebViewTips

参考资料1

参考资料2