Denen blog

株式会社電縁の社員によるブログです。

Swift 4 の WKWebView で alert や confirm に対応してみた

f:id:yasuaki-sakai:20190213110415p:plain

こんにちは、イノベーションオフィスの吉田です。

最近 Swift 4 で WKWebView を使う機会が有ったのでメモ的投稿です。

 

WebView を使うとアプリが簡単に作れて便利なのですが、 JavaScript の alert や confirm にデフォルトでは対応してくれていませんでした。

というわけでざっと調べてみたのですが Swift 4 で対応している記事が見つからなかったので書いてみました。

早速コードになります。

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    
    let wkWebView1 = WKWebView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let urlString1 = "https://www.google.co.jp/"
        let encodeUrlString1 = urlString1.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
        
        let url1 = NSURL(string: encodeUrlString1!)
        let request1 = NSURLRequest(url: url1! as URL)
        
        let userAgentStr = "My Browser App"
        wkWebView1.customUserAgent = userAgentStr
        
        wkWebView1.uiDelegate = self
        wkWebView1.navigationDelegate = self
        
        wkWebView1.frame = view.frame
        view.addSubview(wkWebView1)
        wkWebView1.load(request1 as URLRequest)
    }

    // alert対応
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
        let otherAction = UIAlertAction(title: "OK", style: .default) {
            action in completionHandler()
        }
        alertController.addAction(otherAction)
        present(alertController, animated: true, completion: nil)
    }
    
    // confirm対応
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
            action in completionHandler(false)
        }
        let okAction = UIAlertAction(title: "OK", style: .default) {
            action in completionHandler(true)
        }
        alertController.addAction(cancelAction)
        alertController.addAction(okAction)
        present(alertController, animated: true, completion: nil)
    }
    
    // prompt対応
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        
        // variable to keep a reference to UIAlertController
        let alertController = UIAlertController(title: "", message: prompt, preferredStyle: .alert)
        
        let okHandler: () -> Void = {
            if let textField = alertController.textFields?.first {
                completionHandler(textField.text)
            } else {
                completionHandler("")
            }
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
            action in completionHandler("")
        }
        let okAction = UIAlertAction(title: "OK", style: .default) {
            action in okHandler()
        }
        alertController.addTextField() { $0.text = defaultText }
        alertController.addAction(cancelAction)
        alertController.addAction(okAction)
        present(alertController, animated: true, completion: nil)
    }
    
}

WKUIDelegate を継承して、alert / confirm / prompt を引っ掛けてあげる感じですね。

参考になれば幸いです。

 

それでは。

 

書いた人:イノベーションオフィス 室長 吉田

f:id:yasuaki-sakai:20171204190702j:plain