Embeds and controls web content in SwiftUI with WebKit for SwiftUI, including WebView, WebPage, navigation policies, JavaScript execution, observable page state, link interception, local HTML or data loading, and custom URL schemes. Use when building iOS 26+ article/detail views, help centers, in-app documentation, or other embedded web experiences backed by HTML, CSS, and JavaScript.
Embeds and controls web content in SwiftUI with WebKit for SwiftUI, including WebView, WebPage, navigation policies, JavaScript execution, observable page state, link interception, local HTML or data loading, and custom URL schemes. Use when building iOS 26+ article/detail views, help centers, in-app documentation, or other embedded web experiences backed by HTML, CSS, and JavaScript.
SwiftUI WebKit
Embed and manage web content in SwiftUI using the native WebKit-for-SwiftUI APIs introduced for iOS 26, iPadOS 26, macOS 26, and visionOS 26. Use this skill when the app needs an integrated web surface, app-owned HTML content, JavaScript-backed page interaction, or custom navigation policy control.
Back-deploy below iOS 26 or use missing legacy-only WebKit features
WKWebView fallback
Prefer WebView and WebPage for modern SwiftUI apps targeting iOS 26+ when the new API surface covers the feature. Apple’s WWDC25 guidance frames existing UIKit/AppKit WebKit wrappers in SwiftUI apps as good candidates to try migrating, not as a blanket mandate to delete every fallback.
Do not use embedded web views for OAuth. That stays an ASWebAuthenticationSession flow.
Displaying Web Content
Use the simple WebView(url:) form when the app only needs to render a URL and SwiftUI state drives navigation.
Use callJavaScript(_:arguments:in:contentWorld:) to evaluate JavaScript functions against the page.
Pass a JavaScript function body, not a wrapped function declaration or call expression. Prefer arguments for Swift-provided values instead of interpolating untrusted strings into the script.
let script ="""
const headings = [...document.querySelectorAll('h1, h2')];
return headings.map(node => ({
id: node.id,
text: node.textContent?.trim()
}));
"""let result =tryawait page.callJavaScript(script)
let headings = result as? [[String: Any]] ?? []
You can pass values through the arguments dictionary and cast the returned Any into the Swift type you actually need.
let result =tryawait page.callJavaScript(
"return document.getElementById(sectionID)?.getBoundingClientRect().top ?? null;",
arguments: ["sectionID": selectedSectionID]
)
Handle empty and JavaScript null results deliberately: no explicit return produces nil, while an explicit JavaScript null returns NSNull.
Important boundary: the native SwiftUI WebKit API clearly supports Swift-to-JavaScript calls, but it does not expose an obvious direct replacement for WKScriptMessageHandler. If you need coarse JS-to-native signaling, a custom navigation or callback-URL pattern can work, but document it as a workaround pattern, not a guaranteed one-to-one replacement.