35
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アイエンター #1Advent Calendar 2018

Day 15

【Swift4】WKWebViewを使ったときに調べたこと

Last updated at Posted at 2018-12-15

##はじめに

WKWebViewを初めて使って調べたときに、
バラバラとした情報が多い印象で、
少々苦労した記憶があるので、備忘録として記載します。

とはいえ初心者向けです・・・!(`・ω・´)

##WKWebViewとは?

 iOS 8では、これまで用いられていたブラウザエンジンであるUIWebViewに加え、「WKWebView」という新しいエンジンが追加されました。
WKWebViewはその実行速度、安定性、そして機能面でも、UIWebViewを大幅に向上しています。
要するに、WKWebViewを用いるだけで、アプリの実行速度が大幅にアップする。

引用元:ハイブリッドアプリの動作性能を飛躍的にアップさせるiOS 8の新ブラウザエンジンを検証する

要するに、アプリでWebページを表示している、あれです。(`・ω・´)

iOS8.0以上では、WKWebViewを使用するのが主流のようです。
(UIWebViewは非推奨。)

そして、WKWebViewは、storyboard上で設定できないらしい・・・!
(ソース:WKWebViewと向き合ってみた)ので、
今回は、WKWebViewをコードで画面に配置しました。

##環境

  • X-code 9.4.1
  • Swift4.1

##WKWebViewの基本的なデリゲートメソッド
WKNavigationDelegateに関してです。
記載しているメソッド以外にも色々ありますが、(どれを使うべきか、悩みました・・・)
今回は実際に使ったことのある基本的なメソッドを、4つ記載しています。

###①Webページの読み込み開始時に、処理を実行したい

.swift
/// リクエスト開始時に呼ばれる
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // ここに処理を書く!
        decisionHandler(WKNavigationActionPolicy.allow) // WKNavigationActionPolicyを書かないとクラッシュします!
}
  • Post時に呼ばれるイベント
  • そのままページを表示するか、読み込みを中止する(ページを表示しない)かを決める
  • リダイレクトが起これば連続して呼ばれる
  • navigationTypeを見るとクリックよる遷移か、リダイレクトによる遷移かが分かる
  • decisionHandler(WKNavigationActionPolicy.allow)
    →ページを表示する
  • decisionHandler(WKNavigationActionPolicy.cancel)
    →ページを表示しない

WKNavigationActionPolicyを書かないと、以下のようなエラーでクラッシュします。
地味に萎えるので、忘れないように注意しましょう!

Decides whether to allow or cancel a navigation.
Your delegate can either call the block immediately or save the block and call it asynchronously at a later time.

###②Webページが表示完了した時に、処理を実行したい

cookieの値チェックなどは、ここで行うと良さそうです。(`・ω・´)
(このメソッドか呼ばれる前は正しいcookieの値が取得できないことがありました。)

.swift
    /// WebView表示完了
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // ここに処理を書く!
    }

###③Webページ読み込みエラー時に、処理を実行したい

オフラインのチェック等をしたい場合に、これを使ってうまくいきました。(`・ω・´)

.swift
    /// WebView読み込み時にエラーが発生
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        // ここに処理を書く!
    }

###④Webページ読み込み失敗時に、処理を実行したい

.swift
    ///  WebView読み込み失敗
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        // ここに処理を書く!
    }

+.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+ +.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+ +.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+ 

ちなみに、これらのメソッドは、親ViewControllerを拡張して

.swift
extension ViewController: WKNavigationDelegate {
}

内で呼びます。

それと、基本的なことですが、

.swift
import WebKit

を書かないと、上記のデリゲートメソッドを書いてもエラーになるので、忘れないようにしてください・・・w
参考:WebKit

##WKWebViewをAutoLayout設定してViewに配置する

画面いっぱいにWebViewを表示するだけなら
AutoLayoutはあまり意識しないでも済む(?!)かもしれませんが、
WebViewのサイズ調整、AutoLayoutが必要な場面は多々あるかなと思います。
(iPhoneXだとレイアウト調整必要ですし・・・)

今回は、フルスクリーン表示用と、
tabBarControllerに表示用に適当なメソッドを作りましたので、
その両方を、使い方と一緒に備忘録として記載しておきます。

※ちなみに、このtabBarControllerにwebViewを貼るだけをコードで書いてますw
ご了承ください。
スクリーンショット 2018-12-15 16.10.13.png

フルスクリーンに表示.swift

    /// WebView画面(フルスクリーンに表示時)のAutoLayoutを設定
    ///
    /// - Parameters:
    ///   - webView: 表示するWebView
    ///   - view: WKWebViewを乗せるview
    public func setLayoutFullScreenWebView(webView: WKWebView, view: UIView) {

        // AutoLayout設定
        webView.translatesAutoresizingMaskIntoConstraints = false

        // webViewの幅をviewに合わせる
        view.addConstraints([NSLayoutConstraint(item:webView, // AutoLayoutを設定する対象のview(ここではWKWebViewを指定)
                                           attribute:NSLayoutAttribute.width, // AutoLayout設定対象のViewの起点を指定
                                           relatedBy:NSLayoutRelation.equal, // 2つのview(ここでは親viewとWKWebView)の拘束関係を示すもの
                                              toItem:view, // 拘束の基準となるview
                                           attribute:NSLayoutAttribute.width, // 設定値はattributeと内容は同じ
                                          multiplier:1.0, // 親viewに対して何パーセントの大きさにするかを設定(例:70%なら0.7)
                                            constant:0)]) // 位置に加えるオフセット (例:親のビューの中心を基準にそろえるものの、それに対して常に30ポイントだけ正方向にずらしたい場合は30を設定する)
        // webViewの高さをviewに合わせる
        view.addConstraints([NSLayoutConstraint(item:webView,
                                                attribute:NSLayoutAttribute.height,
                                                relatedBy:NSLayoutRelation.equal,
                                                toItem:view,
                                                attribute:NSLayoutAttribute.height,
                                                multiplier:1.0,
                                                constant:0)])
    }
tabBarControllerに表示.swift
    /// WebView画面(tabbarControllerに表示時)のAutoLayoutを設定
    ///
    /// - Parameters:
    ///   - webView: 表示するWebView
    ///   - view: WebViewを乗せるview
    public func setLayoutWebView(webView: WKWebView, view: UIView) {
        // AutoLayout設定
        webView.translatesAutoresizingMaskIntoConstraints = false
        // webViewの上端をviewに合わせる
        view.addConstraints([NSLayoutConstraint(item:webView,
                                                attribute:NSLayoutAttribute.top,
                                                relatedBy:NSLayoutRelation.equal,
                                                toItem:view,
                                                attribute:NSLayoutAttribute.top,
                                                multiplier:1.0,
                                                constant:0)])
        // webViewの幅をviewに合わせる
        view.addConstraints([NSLayoutConstraint(item:webView,
                                                attribute:NSLayoutAttribute.width,
                                                relatedBy:NSLayoutRelation.equal,
                                                toItem:view,
                                                attribute:NSLayoutAttribute.width,
                                                multiplier:1.0,
                                                constant:0)])
        // webViewの下端をviewに合わせる
        view.addConstraints([NSLayoutConstraint(item:webView,
                                                attribute:NSLayoutAttribute.bottom,
                                                relatedBy:NSLayoutRelation.equal,
                                                toItem:view,
                                                attribute:NSLayoutAttribute.bottom,
                                                multiplier:1.0,
                                                constant: -49.0)]) // 画面下のtabbarを考慮
    }

translatesAutoresizingMaskIntoConstraints
コードでAutoLayoutを設定する時にはtranslatesAutoresizingMaskIntoConstraintsをオフにする必要があるみたい(デフォルトがONで思った通りのAutoLayoutが設定できない場合があるそう)なので、オフにします。

NSLayoutConstraint
レイアウトはNSLayoutConstraintを使用しています。
(参考にした記事は、いちばん下の参考一覧に記載しています。)

##Webページを表示するリクエスト

実際にURLのWebページを表示するリクエストです!
これも、複数のViewControllerから呼び出せるように適当なメソッドを作っています。

.swift
    /// リクエスト
    ///
    /// - Parameters:
    ///   - urlString: 表示するURL
    ///   - webView: 表示先のwebView
    public func requestUrl(urlString: String, webView: WKWebView) {
        // URL設定
        let encodedUrlString = urlString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
        // Webページを読み込む
        let url = NSURL(string: encodedUrlString!)
        let request = NSURLRequest(url: url! as URL)
        webView.load(request as URLRequest)
    }

おおまかな手順は下記です。(`・ω・´)

#####①URLエンコード

#####②URLをNSURLに変換
#####③NSURLRequestでリクエストを生成
#####④webViewにURLのWebページを表示するようにリクエスト

この辺に関しては、WKWebViewではありませんがswift:UIWebViewでwebページを引っ張ろう!!の記事がわかりやすかったです。

##実際にWebページを表示してみる

呼び出し元.swift

    private var webView: WKWebView = WKWebView()

    // 表示するURL
    private let urlString: String = "https://www.yahoo.co.jp/"
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // WKWebViewの追加
        webView = WKWebView(frame:CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height))
        view.addSubview(webView)
        
        // 画面いっぱいに表示
        self.setLayoutFullScreenWebView(webView: webView, view: view)

        webView.navigationDelegate = self

        self.requestUrl(urlString: urlString, webView: self.webView)
    }

Simulator Screen Shot - iPhone 8 Plus - 2018-12-15 at 15.38.03.png

\(^o^)/

簡単にwebViewを表示することができましたw

##まとめ
勉強し始めの頃は、自分の好きなサイトをwebViewに表示するだけでも、
表示できたときに嬉しいですし、地味にテンション&モチベーションもあがるので
試しにWKWebViewを使ってみるのは、個人的に初心者の方におすすめできます\(^o^)/

##参考・WKWebView関連記事

35
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?