Jeremiah
Jeremiah

Reputation: 199

iOS WKWebView javascript alert crashing on ipad

I'm using the solution in this answer that properly displays javascript alert/confirm/etc boxes and it works great on iphones.

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

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler()
    }))

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


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)
    }))

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


func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping (String?) -> Void) {

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

    alertController.addTextField { (textField) in
        textField.text = defaultText
    }

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        if let text = alertController.textFields?.first?.text {
            completionHandler(text)
        } else {
            completionHandler(defaultText)
        }
    }))

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

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

However on ipads clicking anything with a javascript action crashes the app with [UIPopoverPresentationController presentationTransitionWillBegin]

Fatal Exception: NSGenericException Your application has presented a UIAlertController () of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.

I'm sort of at a loss here to fix this. Can anyone give some advice on this? I have tried various ways to use

the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'

in my code, but wasn't successful. Any advice appreciated on this. Thanks.

Upvotes: 1

Views: 1354

Answers (1)

Jeremiah
Jeremiah

Reputation: 199

Figured this one out - wanted to leave a note for anyone else that runs in to this. a small change to the end of the functions:

replace

    present(alertController, animated: true, completion: nil)

with

    if let presenter = alertController.popoverPresentationController {
        presenter.sourceView = self.view
    }

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

Upvotes: 3

Related Questions