令和元年のご時世でもWebViewでラッピングしたアプリを作りたいという要望は多くSwiftUIでWebViewを使う方法について調べたのでメモ
ソースコードはGithubにも上げてあります
#開発環境
- MacOS: 10.14.6
- Xcode: 11.1
#実装
###WKWebViewのセットアップ
WKWebView
がないので、UIViewRepresentable
を利用してWKWebView
を表示するView
を用意する
WebView.swift
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
var loadUrl:String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(URLRequest(url: URL(string: loadUrl)!))
}
}
このWebViewを使えばWebサイトの表示ができる。
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
WebView(loadUrl: "https://www.apple.com")
}
}
###画面遷移を検知する
単純にさっきのWebView
にDelegate追加してstruct WebView: UIViewRepresentable, WKWebViewDelegate
みたいにできればいいけど、Class
ではなく、struct
なのでエラーが出てしまいdelegateをそのまま実装できない。
今回はObserverを使ってURLの変化を検知して対応した。さっきのWebView
にObservableObject
を追加する感じ。
WebView.swift
class observable: ObservableObject {
@Published var observation:NSKeyValueObservation?
}
struct WebView: UIViewRepresentable {
var loadUrl:String
@ObservedObject var observe = observable()
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
observe.observation = uiView.observe(\WKWebView.url, options: .new) { view, change in
if let url = uiView.url {
print("Page loaded: \(url)")
}
}
uiView.load(URLRequest(url: URL(string: loadUrl)!))
}
}
ここではWKWebView
のurl
を比べているけど、title
や他のプロパティでも可能なので、ロード中かどうか知りたければisLoading
をobserve
するようにすれば大丈夫。