WKWebViewのRXデータバインディングを実装する

概要

今回はWKWebViewのRxSwiftのローディング処理について見ていきます。

実はRxSwiftにWKWebViewのものがないためかrxのプロパティがありません。

ただし公式がWKWebViewに対するライブラリを提供していますのでこれをインストールして貰えればrxが使えるようになります。

github.com

こちらをcocoapodでインストールすることでWKWebViewに対してrxが使えるようになります。

ただWKWebViewはiOS11未満をサポートしている場合storyboardにUIKitを置くとワーニングが出てしまいます。

そのためコード側でWKWebView を作成してviewに乗せるという処理をしていきます。

cocoapodのライブラリについて

今回はWKWebView用のライブラリを追加するのでcocoapodのpodfileを下のように変更します。

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'RxSwitch' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for RxSwitch
    pod 'RxSwift', '~> 4.0'  # 追加する
    pod 'RxCocoa', '~> 4.0'  # 追加する
    pod 'RxWebKit' # 追加する

  target 'RxSwitchTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'RxSwitchUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

RxSwiftの他にRxWebKitを追加しました。

これをインストールしないとWKWebView に対してrxが使えません。

ViewControllerのソースコードについて

今回はViewController.swiftのコード側だけの実装となります。

ViewController.swift

import UIKit
import RxCocoa
import RxSwift
import WebKit
import RxWebKit

class ViewController: UIViewController {
    
    private var webView: WKWebView! = {
        let configuration = WKWebViewConfiguration()
        return WKWebView(frame: .zero, configuration: configuration)
    }()
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupWebView()
    }
    
    private func setupWebView() {
        // Rxの実装
        webView.rx.url
            .subscribe(onNext: { url in
                if let url = url {
                    print("URL: \(url)")
                }
            })
            .disposed(by: disposeBag)
        
        // storyboard にないのでviewに乗せる
        self.view.addSubview(webView)
        
        // webViewのオートレイアウトを設定する
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.webView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
        self.webView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
        self.webView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        self.webView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        
        // URLの読み込み
        if let url = URL(string: "https://www.google.com/") {
            let urlRequest = URLRequest(url: url)
            webView.load(urlRequest)
        }
    }
}

各所に補足のコメントを記載しました。

注意点は今回はWKWebViewをコード上で生成しましたのでviewにのせてオートレイアウトを張ることです。

コードとしてみてみるとRxを使わないコードと似たような感じになりますね。

WKWebViewはブラウザ内でJavaScriptを実行したりするときにデリゲートを多用するのでそのときにRxの真価が発揮されます。

挙動を確認してみよう

これでアプリをビルドしてみましょう。

画面が表示されてGoogleのページが表示されたら成功です。

f:id:qed805:20190308001434p:plain
wk_webview_2

今回はこれで終わります。