Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【SwiftUI】WKWebViewの戻る/進む/再読み込みの機能を実装する

 

はじめに

【SwiftUI】WKWebViewを使えるようにする - Swift・iOSに記載した実装内容を修正して、WKWebView用のボタン(戻る/進む/再読み込み)を設置してみたので記事に残します。

 

開発環境

 

実装

WebView.swift

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    var webView = WKWebView()
    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 webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            // 表示しているページのURL
            print(webView.url?.absoluteString ?? "")
            // 表示しているページのタイトル
            print(webView.title ?? "")
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> WKWebView {
        return webView
    }
    
    func updateUIView(_ webView: WKWebView, context: Context) {
        // makeCoordinatorで生成したCoordinatorクラスのインスタンスを指定
        webView.uiDelegate = context.coordinator
        webView.navigationDelegate = context.coordinator
        
        // スワイプで画面遷移できるようにする
        webView.allowsBackForwardNavigationGestures = true
        
        guard let url = URL(string: urlString) else {
            return
        }
        let request = URLRequest(url: url)
        webView.load(request)
    }
    
    // 前のページに戻る
    func goBack() {
        webView.goBack()
    }
    
    // 次のページに進む
    func goForward() {
        webView.goForward()
    }
    
    // ページをリロードする
    func reload() {
        webView.reload()
    }
}

 

ContentView.swift(WebViewの使用例)

import SwiftUI

struct ContentView: View {
    private var webView = WebView(urlString: "{表示したいURL}")
    
    var body: some View {
        VStack() {
            webView
            
            HStack {
                Spacer()
                
                Button(action: {
                    webView.goBack()
                }) {
                    Image(systemName: "chevron.backward")
                }
                .font(.title3)
                .padding(15)
                
                Spacer()
                
                Button(action: {
                    webView.goForward()
                }) {
                    Image(systemName: "chevron.forward")
                        .font(.title3)
                        .padding(15)
                }
                
                Spacer()
                
                Button(action: {
                    webView.reload()
                }) {
                    Image(systemName: "arrow.counterclockwise")
                        .font(.title3)
                        .padding(15)
                }
                
                Spacer()
            }
            .background(Color(red: 0.9, green: 0.9, blue: 0.9))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 

おわりに

簡単に実装できるとはいえ、UIViewRepresentableを使わなくてもSwiftUIでWKWebView使えるようになってほしい・・・。

 

参考