WKWebView 遇到过的坑

在上个项目中,使用到了 WKWebView 实现 JS 与原生的方法互调,不过在使用的时候,遇到了许多的 bug ,一一列出来,以做警示

1、无弹框的问题

在 WK 中,默认是没有弹出框的,如果你需要设置弹出框,则需要重写三个方法
+ webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:
+ webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:
+ webView:runJavaScriptTextInputPanelWithPrompt:initiatedByFrame:completionHandler:

分别对应的是确认的、提示的、文字输入的三种弹出框。
具体的实现如下:

#pragma mark - <WKUIDelegate>
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    UIAlertController *controller = [UIAlertController alertControllerWithTitle:message message:@"" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }];
    [controller addAction:action];
    [self presentViewController:controller animated:YES completion:nil];
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {

    UIAlertController *controller = [UIAlertController alertControllerWithTitle:message message:@"" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }];
    [controller addAction:action];
    UIAlertAction *cancle = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }];
    [controller addAction:cancle];
    [self presentViewController:controller animated:YES completion:nil];
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {

    UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [controller addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {

    }];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(controller.textFields.lastObject.text);
    }];
    [controller addAction:action];
    [self presentViewController:controller animated:YES completion:nil];
}

不要怪我不写注释,实在是没什么好写的,代码猛地一看有点多,实际认真看一下也就那么回事。

2、初始的时候调用 Web 方法无反应

这个问题主要是出在网页还没加载结束,那时候可能方法都没出来,那又怎么可能会加载成功呢,解决方案的话就是在Web加载结束后再调用,代码如下:

#pragma mark - <WKNavigationDelegate>
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [webView evaluateJavaScript:@"" completionHandler:nil];
}

evaluateJavaScript就是方法名及其参数,具体的不详细说明,大致就是如此。

3、WK 无法调用本地方法

WK 调用本地方法需要注意必须在 config 中设置 [config.userContentController addScriptMessageHandler:self name:@"next"]; next 即为方法名。然后实现userContentController:didReceiveScriptMessage: 方法,在方法中接取调用。

#pragma mark - <WKScriptMessageHandler>

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"next"]) {
        //
    }
}

如果这边你确定写的没错了,那就是服务器那边的问题了。

4、WK 拍照、照片库上传无效

无效的原因是默认关闭JS的交互,不允许JS自动打开窗口,解决方案的话重新打开即可:

    config.preferences=[[WKPreferences alloc]init];
    config.preferences.minimumFontSize = 10;
    config.preferences.javaScriptEnabled = true;
    // 默认是不能通过JS自动打开窗口的,必须通过用户交互才能打开
    config.preferences.javaScriptCanOpenWindowsAutomatically =true;

5、 WK 照片点击上传的时候,出现返回上一个控制器

如果你出现返回上一个控制器,那么说明,或者你或者你的导航栏控制器是通过 presentViewController 进来的。
这一点的话,我怀疑是系统的BUG,想要成功上传,必须保证这个 Controller 或者 NavigationController 没有 PresentingController,即这个 Controller 或者 NavigationController 需要是 RootController。否则会自动 dismissController。
解决方案的话就是在每次 presentViewController 的时候,都将下一个视图设置为 RootController ,并移除自己:

        UIViewController  *main   =   [UIViewController new];
        [UIApplication sharedApplication].delegate.window.rootViewController = main;
        [self presentViewController:main animated:YES completion:^{
            [self dismissViewControllerAnimated:NO completion:nil];
        }];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值