LoginSignup
6
10

More than 3 years have passed since last update.

SwiftUIでのWebViewを扱うときの注意点

Posted at

はじめに

SwiftUIではWebViewに相当するものが用意されていないため、UIViewRepresentableを使ってUIKitのWKWebViewをバインディングしたものを自作して利用するのが一般的だと思います。

実際の方法は@wiii_naさんの記事が参考になります。

この方法はiPhoneでの利用は問題ありませんが、iPadだと問題が出てきます。

具体的には、HTMLのselect要素を選択したときに表示されるUIPopoverController的なUIを選択すると、画面が勝手にリロードされて要素を選択することができません。

IMG_0142.PNG

理由

このUIはどうやらWebKitのUI部品ではなく、OSのUI部品を利用しているらしく、WKWebViewがUIViewControllerのSubViewとして存在している必要があるようです。

参考:StackOverFlowのスレッド

対応方法

WKWebViewをSubViewとして持つUIViewControllerを作ってやり、UIViewControllerRepresentableでバイディングしてやればOKです。

import SwiftUI
import WebKit

struct WebView: UIViewControllerRepresentable {
    var req : URLRequest

    class Coodinator: NSObject, WKNavigationDelegate, WKUIDelegate {
        var parent : WebView

        init(_ parent: WebView) {
            self.parent = parent
        }

        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            print("load started")
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            print("load finished")
        }

        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
            print(error)
        }
    }

    func makeCoordinator() -> WebView.Coodinator {
        return Coodinator(self)
    }

    func makeUIViewController(context: Context) -> EmbeddedWebviewController {
        let webViewController = EmbeddedWebviewController(coordinator: context.coordinator)
        webViewController.loadUrl(req)

        return webViewController
    }

    func updateUIViewController(_ uiViewController: EmbeddedWebviewController, context: UIViewControllerRepresentableContext<WebView>) {

    }
}

class EmbeddedWebviewController: UIViewController {

    var webview: WKWebView

    public var delegate: WebView.Coordinator? = nil

    init(coordinator: WebView.Coordinator) {
        self.delegate = coordinator
        self.webview = WKWebView()
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        self.webview = WKWebView()
        super.init(coder: coder)
    }

    public func loadUrl(_ req: URLRequest) {
        webview.load(req)
    }

    override func loadView() {
        self.webview.navigationDelegate = self.delegate
        self.webview.uiDelegate = self.delegate
        view = webview
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

struct WebView_Previews: PreviewProvider {

    static var previews: some View {
        VStack{
            WebView(req: self.makeURLRequest())
        }
    }

    static func makeURLRequest() -> URLRequest {
        let request = URLRequest(url: URL(string: "https://www.google.co.jp")!)
        return request
    }
}
6
10
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
6
10