WKWebView 展示来自 JS 的警告信息

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

在现在的开发中,要将 H5 页面展示在 App 中主要用到 WKWebView。在 Web 网页中有一些经典的 Alert 弹窗,为了支持这种警报,需要实现一些 WKWebView.uiDelegate 回调。这篇文章主要来讲讲如何在 iOS WKWebView 上支持各种 Javascript 警报的代码示例:

UIDelegate

首先你的 webView 需要支持 WKWebView.uiDelegate 协议,它包含支持 Javascript 警报所需的方法。

ini 复制代码
webKitView?.uiDelegate = self

WKWebView Javascript 警报消息

当 Web 上执行 window.alert 的时候,系统会调用 webView(_:, runJavaScriptAlertPanelWithMessage:, initiatedByFrame:, completionHandler:) 代理方法, 我们需要在这个方法中做出承接:

less 复制代码
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
    
    let alert = UIAlertController(
        title: "这是一个来自 JS 的 Alert",
        message: "Alert 的内容为:\(message)",
        preferredStyle: .alert
    )

    // 增加一个 完成 按钮
    let okAction = UIAlertAction(
        title: "完成",
        style: .default,
        handler: { _ in
            completionHandler()
        }
    )
    alert.addAction(okAction)

    present(alert, animated: true, completion: nil)
}

当 Web 上执行 window.alert('测试 alert') 的时候,就会调用这个方法,并弹出我们的 UIAlertController:

Javascript 确认操作

当在 js 中执行 window.confirm("message") 时就会调用 webView(_:, runJavaScriptConfirmPanelWithMessage:, initiatedByFrame:, completionHandler:) 方法,我们可以在此拦截,并自己弹出一个 UIAlertController 来让用户确认。

这个方法中的 completionHandler 来回调给 WebView 用户点了是或者否。

less 复制代码
func webView(_ webView: WKWebView,
    runJavaScriptConfirmPanelWithMessage message: String,
    initiatedByFrame frame: WKFrameInfo,
    completionHandler: @escaping (Bool) -> Void) {

    // Set the message as the UIAlertController message
    let alert = UIAlertController(
        title: "这是一个来自 JS 的确认弹窗",
        message: "需要确认的内容为:\(message)",
        preferredStyle: .alert
    )

    // 添加一个确认按钮
    let okAction = UIAlertAction(
        title: "确认",
        style: .default,
        handler: { _ in
            // 当用户点击确认,回调 true 给 webView
            completionHandler(true)
        }
    )
    alert.addAction(okAction)

    // 添加一个取消按钮
    let cancelAction = UIAlertAction(
        title: "取消",
        style: .cancel,
        handler: { _ in
            // 当用户点击取消,回调 false 给 webView
            completionHandler(false)
        }
    )
    alert.addAction(cancelAction)

    present(alert, animated: true, completion: nil)
}

当 H5 上 js 调用 window.confirm("你确认吗?"),就会在页面上看到:

Javascript 输入提示

当在 js 中执行 window.prompt() 时就会调用 webView(_:, runJavaScriptTextInputPanelWithPrompt prompt:, defaultText:, initiatedByFrame frame:, completionHandler:) 方法,我们可以在此拦截,并自己弹出一个 UIAlertController 来让用户输入内容。

less 复制代码
func webView(_ webView: WKWebView,
    runJavaScriptTextInputPanelWithPrompt prompt: String,
    defaultText: String?,
    initiatedByFrame frame: WKFrameInfo,
    completionHandler: @escaping (String?) -> Void) {
    
    let alert = UIAlertController(
        title: "这是一个来自 JS 的输入框弹窗",
        message: "提示词为:\(prompt)",
        preferredStyle: .alert
    )

    // 添加一个输入框
    alert.addTextField()
    
    // 把默认值写进输入框
    alert.textFields?.first?.text = defaultText

    // 添加一个提交按钮
    let submitAction = UIAlertAction(
        title: "提交",
        style: .default,
        handler: { [unowned alert] _ in
            // 把用户输入的内容回调给 js
            let input = alert.textFields?.first
            completionHandler(input?.text)
        }
    )
    alert.addAction(submitAction)

    present(alert, animated: true, completion: nil)
}

当 js 执行 window.prompt('请输入内容', '这是输入框的默认值'),就会在页面上看到我们自定义的带输入框的 Alert:

重要的一点

如果你决定使用这种方式承接 js 的警报弹窗,那么这三个方法的 completionHandler 回调一定要执行,否则当 js 调用到对应的方法时 App 会发生崩溃,崩溃日志为:

vbnet 复制代码
Terminating app due to uncaught exception 
'NSInternalInconsistencyException', reason: 
'Completion handler passed to 
-[TestProject.ViewController webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:] 
was not called'

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
传奇开心果编程12 小时前
【SwiftUI提高练中学】第13课 实时活动与灵动岛:ActivityKit 实战
学习·ui·ios·swiftui·swift
可乐鸡翅yeah_17 小时前
M3U8 防盗链 URL‑Token 签名,新手开发实操避坑
开发语言·javascript·ios·音视频·safari
AC赳赳老秦18 小时前
数据采集全链路审计留痕:用 OpenClaw 实现合规审计与追溯
开发语言·汇编·python·php·swift·deepseek·openclaw
传奇开心果编程1 天前
【SwiftUI入门练中学】第17课 通知与后台任务
学习·ui·ios·swiftui·swift
ii_best1 天前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
美狐美颜SDK开放平台2 天前
Android与iOS直播APP美颜有什么区别?视频美颜SDK开发详解
android·ios·音视频·视频美颜sdk
逐流人2 天前
Ceph对象存储与文件系统存储管理:从RADOS网关、S3与Swift到CephFS快照同步
linux·运维·ceph·云原生·云计算·swift·rados
传奇开心果编程3 天前
【SwiftUI入门练中学】第7课 动画与手势:让界面更灵动
学习·macos·ui·ios·swiftui·swift
知潮网3 天前
发售刚十天,9999 元的 iPhone 18 Pro 解锁就重启
ios·iphone
2501_916007473 天前
苹果应用商店App Store上架费用标准及原因解析
android·ios·小程序·https·uni-app·iphone·webview