【Swift】WKWebView まとめ

SwiftでのWKWebView実装方法について自分なりにまとめてみました。

①WKWebViewを作成する

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    @IBOutlet weak var contentView: UIView! //WebViewの表示領域

    private var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //WkWebView 生成
        self.webView = WKWebView(frame: CGRect.zero)

        //デリケート設定
        self.webView.navigationDelegate = self

        //フリップでの戻る・進むを有効にする
        self.webView.allowsBackForwardNavigationGestures = true
        self.contentView.addSubview(self.webView)

        //ページ読み込み
        let url = NSURL(string: "https://www.google.co.jp/")
        let urlRequest = URLRequest(url: url as! URL)
        self.webView.load(urlRequest)
    }

    override func viewDidLayoutSubviews() {
        //WKWebView リサイズ
        self.webView.frame = CGRect(origin: CGPoint.zero, size: self.contentView.frame.size)
    }
}
 


注意点

  • WebKitをインポートする
  • ViewControllerにWKNavigationDelegateを継承させておく
  • xib側でViewControllerの「Adjust Scroll View Insets」項目のチェックを外しておく
     (ここにチェックが入っていると、ナビゲーションバーの高さ分レイアウトがずれてしまう)

  • ②各デリケートの処理

    // MARK: - WKWebView Delegate
        
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let requestURL: URL? = navigationAction.request.url;
            
        // 電話対応
        if(requestURL?.scheme == "tel") {
            var telNumber = String(describing: requestURL!)
            telNumber = telNumber.substring(from: telNumber.index(telNumber.startIndex, offsetBy: 4))
            //アラートを出す
            ・・・
            decisionHandler(.cancel)
            return
        }
        // メール対応
        if(String(describing: requestURL).contains("http://") == false &&
            String(describing: requestURL).contains("https://") == false) {
            if UIApplication.shared.canOpenURL(requestURL!){
                UIApplication.shared.openURL(requestURL!)
            }
            decisionHandler(.cancel)
            return
        }
        // target=blankも開く
        if (navigationAction.navigationType == WKNavigationType.linkActivated) {
            if (navigationAction.targetFrame == nil || navigationAction.targetFrame!.isMainFrame) {
                self.mainWebView.load(URLRequest(url: requestURL!))
                decisionHandler(.cancel);
                return;
            }
        }
        decisionHandler(.allow)
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        // ネットワークインジケータを表示
        UIApplication.shared.isNetworkActivityIndicatorVisible = true;
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // ネットワークインジケータを非表示
        UIApplication.shared.isNetworkActivityIndicatorVisible = false;
    }
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        //ユーザーキャンセルによるエラーは無視する
        if((error as NSError).code != NSURLErrorCancelled) {
            //インジケータ非表示
            UIApplication.shared.isNetworkActivityIndicatorVisible = false;
            //エラー時の処理
            ・・・
        }
    }
    


    ポイント

  • 電話、メール、target=blankへの対応を行う
  • 電話の時はopenURLを叩く前に、アラートを出して「電話をかけてもよろしいでしょうか?」等の確認を挟む
  • 通信中かどうかが分かるように、インジケータを表示させる
  • エラー処理ではユーザーキャンセルによるエラーを無視する

  • ③iOS10に対応する

    input type=“file” 等のリンクをタップした時に写真ライブラリやカメラにアクセスする場合がある。 iOS10では、info.plistに使用目的を記述しておかないとアプリがクラッシュするので注意。
    f:id:dev-oma:20170630112013p:plain

    参考:http://dev.classmethod.jp/smartphone/iphone/ios10-privacy-data-purpose-description/