🥰

SwiftUI標準のWebViewが出たので使ってみた

に公開

はじめに

こんにちは、スペースマーケットでモバイルアプリの開発をしている王です。

最近やっているタスクが佳境になったり、登壇で色々準備したりでやや忙しくなりました。

つい先日のWWDC2025を見まして、WebKit for SwiftUIで紹介されたSwiftUIのWebViewがちょっと気になったので使ってみました!

これまでの話

まず今回の標準WebViewが出る前に、SwiftUIでどうやってWebViewを表示するか簡単に振り返ってみようと思います。

struct WebView: UIViewRepresentable {
    let url: String
    
    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        guard let url = URL(string: url) else {
            return
        }
        let request = URLRequest(url: url)
        uiView.load(request)
    }
}

今までSwitUI標準のWebViewがないので、UIViewRepresentableでWKWebViewをラッパーして表示する方法しかありません。

さらに、大体のアプリのWebViewはWKNavigationDelegateの何らかのメソッドを使うと思うので、コード量も一気に増えてしまいます。

struct WebView: UIViewRepresentable {・・・}

extension WebView {
    class Coordinator: NSObject, WKNavigationDelegate {
        // URLの読み込み監視など色々
        func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
            progressView.start()
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            progressView.end()
        }

        ···省略
    }
}

まあまあ面倒だなと思います。

SwiftUIの標準WebView

では早速使ってみようと思います。
まずWebを表示するだけ

struct SwiftUIWebView: View {
    @State private var webPage = WebPage()
    private let url = URL(string: "https://www.spacemarket.com/")!

    var body: some View {
        WebView(webPage)
            .onAppear {
                // URLを読み込む
                webPage.load(URLRequest(url: url))
            }
    }
}

はい、これで終わりです。

WebPageは監視可能で、Webコンテンツの読み込み状態の取得や、load/reload、JavaScript との連携などが可能です。

次に簡単なプログレスバーも表示したいと思いますが、これもWebPageのestimatedProgressというプロパティで実現します。

var body: some View {
        ZStack {
            WebView(webPage)
                .onAppear {
                    // URLを読み込む
                    webPage.load(URLRequest(url: url))
                }
            // 読み込み進捗バー
            if webPage.estimatedProgress < 1 {
                  ProgressView(value: webPage.estimatedProgress)
                      .progressViewStyle(CircularProgressViewStyle())
            }
        }  
}

最後にページ内検索も実現してみたいと思います。
ここはほぼ公式動画内のコードをそのまま流用しました。

struct SwiftUIWebView: View {
    @State private var webPage = WebPage()
    @State private var isPresented = false
    private let url = URL(string: "https://www.spacemarket.com/")!

    var body: some View {
        NavigationStack {
            WebView(webPage)
                // ページ内検索欄の表示制御
                .findNavigator(isPresented: $isPresented)
                .toolbar {
                    ToolbarItemGroup {
                        Button("Find", systemImage: "magnifyingglass") {
                            isPresented.toggle()
                        }
                    }
                }
                .onAppear {
                    // URLを読み込む
                    webPage.load(URLRequest(url: url))
                }
        }
    }
}

最後に

いかがですか?個人的には、ほんの数行のコードでここまで自然に WebViewが扱えるのは非常に嬉しい進化だと感じました。

今回は細かいナビゲーション制御やJavaScript連携には触れませんでしたが、公式の動画やドキュメントで詳しく解説されています。

iOS 26をサポートする時期になったら、ぜひアプリ内のWebViewをSwiftUI標準のものに置き換えていきたいと思います。

公式ドキュメント

動画
https://developer.apple.com/videos/play/wwdc2025/231/

WebView
https://developer.apple.com/documentation/WebKit/WebView-swift.struct

WebPage
https://developer.apple.com/documentation/webkit/webpage

スペースマーケット Engineer Blog

Discussion