3
Help us understand the problem. What are the problem?

posted at

updated at

【Swift】WKWebViewでJavaScriptを実行する方法

はじめに

WKWebViewでJaveScriptを実行する方法を二つ紹介します。

とりあえずWKWebViewを表示

以下がベースのコードです。
こちらに追加していきます。

import UIKit
import WebKit

class ViewController: UIViewController {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView = WKWebView(frame: view.frame)

        view.addSubview(webView)

        webView.load(URLRequest(url: URL(string: "")!))

    }

}

方法1(読み込み開始時 or 読み込み終了時)

こちらの方法は読み込み開始時もしくは、読み込み終了時に実行されます。
使用用途としては、WebViewの設定や静的サイトの要素ブロックなどが考えられます。
HTMLの読み込み後にSwift.orgのヘッダーを非表示にしてみます

import UIKit
import WebKit

class ViewController: UIViewController {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

+       let hiddenNavigationBarScriptString = "document.getElementsByTagName('nav')[0].style.display='none';"
+       
+       let hiddenNavigationBarScript = WKUserScript(source: hiddenNavigationBarScriptString, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
+       
+       let userContentController = WKUserContentController()
+       
+       userContentController.addUserScript(hiddenNavigationBarScript)
+       
+       let configuration = WKWebViewConfiguration()
+       
+       configuration.userContentController = userContentController
+       
+       webView = WKWebView(frame: view.frame, configuration: configuration)

-       webView = WKWebView(frame: view.frame)

        view.addSubview(webView)

        webView.load(URLRequest(url: URL(string: "https://www.swift.org/")!))

    }

}
通常 JS適用後
simulator_screenshot_4FED424F-1BFC-4E00-8A1A-DD582C45E9F6.png simulator_screenshot_284B6FDF-EA49-459A-826D-4CFA849AFA5B.png

ポイント
WKUserScript(source:, injectionTime:, forMainFrameOnly:)

  • source: JavaScriptのコードをStringで渡す
  • injectionTime: 実行タイミング
    • .atDocumentStart ← 読み込み開始時
    • .atDocumentEnd ← 読み込み終了時
  • forMainFrameOnly: メインフレームのみに反映するならtrue

方法2(任意のタイミング)

こちらの方法は任意のタイミングで実行可能です。
基本的になんでもできると思います。
動的サイトであるQiitaのユーザーページでプロフィールを非表示にしてみます

import UIKit
import WebKit

class ViewController: UIViewController {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView = WKWebView(frame: view.frame)

        view.addSubview(webView)

        webView.load(URLRequest(url: URL(string: "https://qiita.com/SNQ-2001")!))

+       DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+       
+           let hiddenProfileScript: String = "document.getElementsByClassName('css-t3s93c')[0].style.display='none';"
+
+           self.webView.evaluateJavaScript(hiddenProfileScript) { _, _ in
+
+           }
+           
+       }

    }

}
通常 JS適用後
simulator_screenshot_6B7B4ADD-AA68-48B6-893F-F37EE49D5509.png simulator_screenshot_C744C3C3-08B6-4F9E-8A33-8D8E61ADA052.png

ポイント1
動的サイトはHTMLが生成されてから実行しないとスクリプトが動作しないので遅延実行させる
DispatchQueue.main.asyncAfter(deadline: .now() + 1)

ポイント2
必要な場合はresponseから値を受け取る

self.webView.evaluateJavaScript("document.body.innerHTML") { response, error in
    print(response ?? "")
}

参考サイト

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
3
Help us understand the problem. What are the problem?