はじめに
UIViewRepresentableによって、SwiftUIのアプリでもWKWebViewを使えるようにしてみました。
※2021/03/23 追記
SFSafariViewControllerをSwiftUIで使用する方法について、以下記事にしました。
【SwiftUI】SFSafariViewControllerを使えるようにする - Swift・iOS
※2021/04/07 追記
WKWebView用に戻るボタンや進むボタンを実装したい場合は以下の記事を参考にしてください。
【SwiftUI】WKWebViewの戻る/進む/再読み込みの機能を実装する - Swift・iOS
開発環境
・macOS Catalina 10.15.7
・Xcode 12.2
実装部分
WebView.swift
import SwiftUI import WebKit struct WebView: UIViewRepresentable { var urlString: String class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { var parent: WebView init(_ parent: WebView) { self.parent = parent } // "target="_blank""が設定されたリンクも開けるようにする func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { if navigationAction.targetFrame == nil { webView.load(navigationAction.request) } return nil } // URLごとに処理を制御する func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { if let url = navigationAction.request.url?.absoluteString { if (url.hasPrefix("https://apps.apple.com/")) { guard let appStoreLink = URL(string: url) else { return } UIApplication.shared.open(appStoreLink, options: [:], completionHandler: { (succes) in }) decisionHandler(WKNavigationActionPolicy.cancel) } else if (url.hasPrefix("http")) { decisionHandler(WKNavigationActionPolicy.allow) } else { decisionHandler(WKNavigationActionPolicy.cancel) } } } } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() return webView } func updateUIView(_ webView: WKWebView, context: Context) { // makeCoordinatorで生成したCoordinatorクラスのインスタンスを指定 webView.uiDelegate = context.coordinator webView.navigationDelegate = context.coordinator // スワイプで画面遷移できるようにする webView.allowsBackForwardNavigationGestures = true let url = URL(string: urlString)! let request = URLRequest(url: url) webView.load(request) } }
ContentView.swift(WebViewを呼び出す側の実装例)
import SwiftUI struct ContentView: View { var body: some View { WebView(urlString: "{表示したいURL}") } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
おわりに
本記事の通りに実装してもページが表示されない場合は、ATSの設定などを確認してみてください。
また、インジケータの表示やJavaScriptの一部の表示に関しては、可能ではあるものの複雑な実装になってしまったり、情報が少なかったりしたので今回はスキップして今後の課題としました・・・参考リンクは以下に貼っておきます。
参考
・https://developer.apple.com/documentation/swiftui/uiviewrepresentable
・https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit
・https://developer.apple.com/documentation/webkit/wkwebview
・【Swift】WKWebViewでリンク先が開けない場合の対処法(ATS/target=”_blank”) - Swift・iOS
・【Swift】WKWebViewで進む/戻る/更新(リロード)機能を実装する - Swift・iOS
・SwiftUI How can I add an activity indicator in WKWebView? - Stack Overflow
・swift - Implement Javascript Alert and Confirm on WKUIDelegate SwiftUI? - Stack Overflow