Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WebKit::WebView Essentials / Sapporo.swift #1
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yutaro Muta
July 25, 2026
Technology
17
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WebKit::WebView Essentials / Sapporo.swift #1
Yutaro Muta
July 25, 2026
More Decks by Yutaro Muta
See All by Yutaro Muta
Google Nest CamとApple Vision frameworkと猫🐈🐈⬛ / onishi50
yutailang0119
0
280
SwiftUI Inspectorが難しすぎる / Mobile Act OSAKA 18
yutailang0119
0
130
Swift Concurrencyでのスケジュール処理を考える / Mobile Act OSAKA 17
yutailang0119
0
160
猫と暮らすネットワークカメラ生活🐈 ~Vision frameworkでペットを愛でよう~ / iOSDC Japan 2025
yutailang0119
0
450
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
330
Swiftの “private” を テストする / Testing Swift "private"
yutailang0119
0
350
Apple Vision Pro購入RTA 1泊3日弾丸ハワイツアー / RTA: Purchase Apple Vision Pro in Hawaii
yutailang0119
0
1.6k
個人開発のたのしみ / Enjoying personal development
yutailang0119
0
1.1k
バックポートして学ぶ新APIの仕組み
yutailang0119
0
3.4k
Other Decks in Technology
See All in Technology
ここは地獄!つらい朝会を体験することで、チームとしてのより良い振る舞いに気づくワークショップ / The stand-up meeting from hell in the game industry
scrummasudar
0
340
AI Agent を本番環境へ―― Microsoft Foundry × Azure Serverless で作る Enterprise-Ready な基盤
shibayan
PRO
1
520
Power Automateアップデート情報
miyakemito
0
250
ソフトウェアアーキテクチャ研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
2
540
セキュリティ研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
10
9.8k
Jitera Company Deck
jitera
0
570
AI時代の開発生産性を捉え直す — 経営と現場をつなぐ「開発組織のオブザーバビリティ」— / AI Dev Ex Conference 2026
tkyowa
1
1.7k
データ活用研修 問いの発見と仮説構築【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
330
CTOキーノート:AI時代の「つなぐ」を再定義 ― 真のIoTとリアルワールドAI【SORACOM Discovery 2026】
soracom
PRO
0
140
インシデント事例と パッケージの全量解析に学ぶ ソフトウェアサプライチェーンの守り方 / supply-chain-attack-defense
flatt_security
0
1.1k
そのドキュメント、自動化しませんか?
yuksew
1
450
AI_Dev_Day_製造業領域でのAI活用から見た活用の罠と成功に導く実践知.pdf
kintotechdev
0
230
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
187
22k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
420
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
350
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
390
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
450
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
640
WENDY [Excerpt]
tessaabrams
11
39k
Visualization
eitanlees
152
17k
Evolving SEO for Evolving Search Engines
ryanjones
0
250
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
57k
Transcript
WebKit::WebView Essentials id:yutailang0119 2026/7/25 Sapporo.swift #1 1
yutailang0119 • 株式会社はてな ◦ ◦ ◦ • • • @京都オフィス
アプリケーションエンジニア サービスプラットフォーム try! Swift Tokyo Organizer AVP座談会🥽 🐈 2
https://fortee.jp/iosdc-japan-2026/proposal/62b52f01-f999-418b-ab65-a561b49f5202 3
Agenda • WebKit::WebViewを知る・潜る・拡げる • WebViewBackportを作る・拡げる • バックポートからの学び 4
Agenda • Meet / Dive into / Enhance WebKit::WebView •
Meet / Enhance WebViewBackport ◦ @WebViewBackport • Result 5
Meet WebKit::WebView 6
Meet WebKit::WebView • SwiftUI::View実装のWebView ◦ iOS / iPadOS / Mac
Catalyst / macOS / visionOS 26.0+ • 制御状態はWebPageが担当 ◦ @Observable • Meet WebKit for SwiftUI ◦ WWDC25 Session 231 7
Meet WebKit::WebView @available(iOS 26.0, *) struct ContentWebView: View { @State
private var webPage = WebPage() var body: some View { WebView(webPage) .onAppear { webPage.load(URL(string: "https://apple.com")) } } } 8
Dive into WebKit::WebView 9
Dive into WebKit::WebView • Representableを介し、WKWebViewを表示 ◦ class WebPageWebView: WKWebView •
値型で再設計された設定 ◦ WebPage.Configuration <- WKWebViewConfiguration • 抽象化したWKWebView関連Delegateを提供 ◦ WebPage.DialogPresenting <- WKUIDelegateAdapter ◦ WebPage.NavigationDeciding <- WKNavigationDelegateAdapter 10
Dive into WebKit::WebView • WebKitに実装されている • Open Source Software ◦
https://github.com/WebKit/WebKit • SwiftUI APIはSwift overlayに配置 ◦ Source/WebKit/UIProcess/API/Swift/ ▪ UIProcess = アプリ本体のプロセス ▪ 公開APIとUIが置かれる 11
Enhance WebKit::WebView 12
Enhance WebKit::WebView • WebKitを参考にバックポートできそう • 大まかに3つを実装できれば達成可能 ◦ WebViewBackport: SwiftUI::View ◦
WebViewRepresentableBackport: UIViewRepresentable ◦ @Observable class WebPageBackport • ⚠ 回避必要な箇所がある 13
Enhance WebKit::WebView • Appleのoverlayは非公開APIに依存 ◦ internal import WebKit_Internal ◦ import
WebKit_Private ◦ @_spi(...) import SwiftUI • third-partyのバックポートは公開APIだけで 再構築する 14
Enhance WebKit::WebView • ① 公開APIで代替可能 -> 置換・ラップ • ② 内部処理を観測
-> 近似 • ③ 等価なし-> 挙動差・縮小 ◦ SPI、version 15
① 公開APIで代替可能な 置換、ラップ 16
① 公開APIで代替可能な置換、ラップ • Delegateをasyncプロトコルに変換 ◦ WKNavigationDelegate -> NavigationDeciding ◦ WKUIDelegate
-> DialogPresenting • WK* をラップ ◦ FrameInfo・NavigationAction・BackForwardList • NavigationEvent -> some AsyncSequence 17
② 内部処理を 観測して近似 18
② 内部処理を観測して近似 • @ObservableをKVOから再現 ◦ title / url はWKWebView由来のcomputed ◦
読取: getter で access(keyPath:) 登録 ◦ 変更: KVO(.prior) の前/後 -> willSet/didSet ◦ .prior = 変更前通知(willSet 相当) 19
③ 等価なし -> 挙動差・縮小 20
③ 等価なし -> 挙動差 • NavigationEvent.finishedのタイミング差 ◦ WebKit: 描画反映を待つ(SPI) ▪
_do(afterNextPresentationUpdate:) ◦ Backport: didFinish から同期 ◦ 期待挙動と相違 ▪ 完了時にまだ未描画のことがある 21
③ 等価なし -> 挙動差 • BackForwardListをprivateデリゲートで取得 ◦ 履歴変化を知る公開手段がない ▪ @objc(_webView:backForwardListItemAdded:removed:)
◦ privateデリゲート ◦ 未公開のため保証なし -> 将来壊れうる 22
③ 等価なし -> 縮小 • バージョンで欠ける(下位OSに無い) ◦ 提供できない / 上位限定
• バージョンで変わる(型がOSで違う) ◦ 統一シグネチャで包めない 23
③ 等価なし -> 縮小 • 設定もすべては移せない ◦ Configurationは一部プロパティのみ対応 ◦ 未対応の設定は使えない
24
WebViewの Backport達成 25
Meet WebViewBackport 26
Meet WebViewBackport struct ContentWebViewBackport: View { @State private var webPage
= WebPageBackport() var body: some View { WebViewBackport(webPage) .onAppear { webPage.load(URL(string: "https://apple.com")) } } } 27
Meet WebViewBackport • 使用側のインターフェースは同じ • 設定、Delegateもサポート ◦ WebPageBackport.Configuration ◦ any
WebPageBackport.NavigationDeciding ◦ any WebPageBackport.DialogPresenting 28
Enhance WebViewBackport 29
Enhance WebViewBackport @WebViewBackport @available(iOS 26.0, *) struct ContentWebView: View {
@State private var webPage = WebPage() var body: some View { WebView(webPage) .onAppear { webPage.load(URL(string: "https://apple.com")) } } } 30
Enhance WebViewBackport @WebViewBackport @available(iOS 26.0, *) struct ContentWebView: View {
@State private var webPage = WebPage() var body: some View { WebView(webPage) .onAppear { webPage.load(URL(string: "https://apple.com")) } } } 31
@WebViewBackport • macro WebViewBackport ◦ @attached(peer, names: suffixed(Backport)) ◦ これ自身はWebViewバックポートの実装ではない
• マクロを付与したスコープ内の特定文字列を 置換した実装を生成 ◦ WebView -> WebViewBackport ◦ WebPage -> WebPageBackport 32
@WebViewBackport struct ContentWebView: View { ... } ↓Expand Macro struct
ContentWebViewBackport: View { @State private var webPage = WebPageBackport() var body: some View { WebViewBackport(webPage) .onAppear { webPage.load(URL(string: "https://apple.com")) } } 33
@WebViewBackport struct ContentView: View { var body: some View {
if #available(iOS 26.0, *) { ContentWebView() } else { ContentWebViewBackport() } } } 34
Fix WebKit, but… 35
Fix WebKit, but… • WebKitにバグ報告、修正可能 ◦ WebKit Bugzilla • Bug
311485 ▪ <input type="file"> にファイル選択が反応しない • ⚠ OSにバンドルされるまで直らない ◦ OSバックポートされない 36
37
Pitfall of @WebViewBackport 38
Pitfall of @WebViewBackport @WebViewBackport @available(iOS 26.0, *) struct ContentWebView: View
{ @State private var configuration = WebPage.Configuration() @State private var webPage = WebPage() var body: some View { WebView(webPage) .task { let cookies: [HTTPCookie] = ... await configuration.websiteDataStore .httpCookieStore.setCookies(cookies) } 39
Pitfall of @WebViewBackport struct ContentWebView: View { ... } ↓Expand
Macro struct ContentWebViewBackport: View { @State private var configuration = WebPageBackport.Configuration() @State private var webPage = WebPageBackport() var body: some View { WebViewBackport(webPage) .task { let cookies: [HTTPCookie] = ... await configuration.websiteDataStore .httpCookieStore.setCookies(cookies) } 40
Pitfall of @WebViewBackport struct ContentWebView: View { ... } 💥
struct ContentWebViewBackport: View { @State private var configuration = WebPageBackport.Configuration() unrecognized selector @State private var webPage = WebPageBackport() -[WKHTTPCookieStore var body: some View { WebViewBackport(webPage) setCookies:completionHandler:] .task { let cookies: [HTTPCookie] = ... await configuration.websiteDataStore .httpCookieStore.setCookies(cookies) } 41
Pitfall of @WebViewBackport • WKHTTPCookieStore.setCookies(_:) ▪ setCookies(_:completionHandler:) ◦ iOS /
iPadOS / Mac Catalyst / macOS / visionOS 26.0+ • マクロは呼び出し先を検証しない ◦ 実行時エラーが起きうる • iOS 18以下では unrecognized selector 42
Pitfall of @WebViewBackport @WebViewBackport @available(iOS 26.0, *) struct ContentWebView: View
{ var body: some View { WebView(webPage) .task { let cookies: [HTTPCookie] = ... let store = configuration.websiteDataStore.httpCookieStore for cookie in cookies { await store.setCookie(cookie) } } 43
Result 44
Result • 公開APIで“ほぼ”作れる • APIレイヤーとエンジンの境界が限界になる • OSにバンドルされるまでは届かない • WebKit::WebView を「歩いて」読み解いた
45
References 46
References • WebKit/WebKit ◦ • iOS 18向けバックポートから学ぶWebKit::WebViewの歩き方 ◦ • https://github.com/WebKit/WebKit
https://fortee.jp/iosdc-japan-2026/proposal/62b52f01-f999-418b-ab65-a561b49f5202 WKHTTPCookieStore.setCookies(_:) async ◦ https://developer.apple.com/documentation/webkit/wkhttpcookiestore/setcookies(_:completio nhandler:) • WebKit Bugzilla Bug 311485 ◦ • https://bugs.webkit.org/show_bug.cgi?id=311485 SwiftUIにおけるWebViewの実装 - cockscomblog? ◦ https://cockscomb.hatenablog.com/entry/2025/06/04/093418 47
WebKit::WebView利用企業 48 48