【问题标题】:How to dismiss alertController for ipad in WKWebView如何在 WKWebView 中关闭 ipad 的 alertController
【发布时间】:2018-03-20 14:39:35
【问题描述】:

我正在使用 WkWebview 加载网站,并且该网站包含一些 javascript 操作。对于 iPhone,它工作正常,因为在用户选择面板中的可用操作之前,confirmPanel 不允许用户触摸面板外部。但是,对于 iPad,它的功能与 iPhone 不同。每当 我尝试触摸警报面板之外,它会崩溃。请查看代码下方的崩溃日志。我尝试使用 UITapGestureRecognizer,但它仍然无法正常工作。

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

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler(true)
    }))

    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(false)
    }))

    if UIDevice.current.userInterfaceIdiom != .phone {
        if let popoverController = alertController.popoverPresentationController {
            popoverController.sourceView = self.view
            popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
            popoverController.permittedArrowDirections = []
        }
    }

    self.present(alertController, animated: true, completion: nil)
}

错误信息,

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“未调用传递给 -[webViewios.MainVC webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:] 的完成处理程序” *** 首先抛出调用堆栈: (0x21a2f91b 0x211cae17 0x21a2f861 0x287d7293 0x288111b9 0x2886db69 0x21603ac3 0xccd4c 0x8d9e1f 0xcc6d8 0x8d9e1f 0xd1718 0x21603ac3 0x26400cd1 0x263ff26b 0x211e53a9 0x2193ef89 0x219f006f 0x2193f229 0x2193f015 0x22f2fac9 0x26013189 0xd8824 0x215e7873) libc++abi.dylib:以 NSException 类型的未捕获异常终止

【问题讨论】:

    标签: ios swift wkwebview uialertcontroller


    【解决方案1】:

    在 iPad 中,当您呈现操作表时,取消操作会自动映射到操作表控制面板外的点击。您需要更改 UIAlertControllerCancel 按钮的显示方式。

    iPad 上没有取消按钮的更新代码

    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler(true)
        }))
    
        alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
            completionHandler(false)
        }))
    
        if UIDevice.current.userInterfaceIdiom != .phone {
            if let popoverController = alertController.popoverPresentationController {
                popoverController.sourceView = self.view
                popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
                popoverController.permittedArrowDirections = []
            }
        }
    
        self.present(alertController, animated: true, completion: nil)
    }
    

    iPad 上带有取消按钮的代码

    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler(true)
        }))
    
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            completionHandler(false)
        }))
    
        if UIDevice.current.userInterfaceIdiom != .phone {
             alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
                 completionHandler(false)
            }))
            if let popoverController = alertController.popoverPresentationController {
                popoverController.sourceView = self.view
                popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
                popoverController.permittedArrowDirections = []
            }
        }
    
        self.present(alertController, animated: true, completion: nil)
    }
    

    【讨论】:

    • 终于!到目前为止,当我触摸外面时它不会崩溃。但是,我要如何添加取消按钮?
    • 在 iPad 中,当您使用 UIPopoverPresentationController 呈现 UIAlertController 时。取消按钮操作映射到面板外的上下文触摸,它在 iOS 中的 actionSheet 的默认行为。如果您仍需要取消按钮,请为 iPad 添加一个额外的Cancel 按钮,类型为default
    • 嗨,我刚刚发现,我有这个错误线程 1: EXC_BAD_ACCESS (code=1, address=0x20c) at completionHandler(false) 的 ipad 取消按钮。我认为这是因为正在呈现 alertController 并且我单击另一个按钮再次呈现。有时会出现这个错误警告:尝试在 上呈现 已经呈现(null)。
    • 你可以在提交UIAlertController之前检查self.presentingViewController == nil,你能详细解释一下你在哪种情况下得到EXC_BAD_ACCESS
    • 我只有 iPad 2,版本是 iOS 9.3.5。每当我单击 javascript 按钮时,它都会显示警报控制器。所以我尝试多次点击按钮。它显示EXC_BAD_ACCESS...当我尝试在iOS 10和11版本的模拟器上使用它时,到目前为止没有问题。
    【解决方案2】:

    如果UIViewControllerWKWebView 可见,请出示您的UIAlertController。如果不可见,直接执行completionHandler并返回。

    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    
    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler(true)
    }))
    
    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(false)
    }))
    
    if UIDevice.current.userInterfaceIdiom != .phone {
        if let popoverController = alertController.popoverPresentationController {
            popoverController.sourceView = self.view
            popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
            popoverController.permittedArrowDirections = []
        }
    }
    
        if self.viewIfLoaded?.window != nil {
            self.present(alertController, animated: true, completion: nil)
        }
        else {
            completionHandler()
        }
    }
    

    【讨论】:

    • 我可以知道如何配置 isVisible() 吗?并且 completionHandler() 缺少参数。它需要一个 BOOL 并且不允许为空。
    • 当我触摸警报面板外时它仍然崩溃。此外,completionHandler() 需要一个参数。我试了真假,也没用。
    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多