WWDC Quick Look 💓 By SwiftGGTeam
What's new in WKWebView

What's new in WKWebView

观看原视频

Highlight

WKWebView 在 iOS 16 和 iPadOS 16 中新增全屏元素、动态视口范围、页面查找、iframe 级内容屏蔽、iPad 加密媒体播放,以及带 web-browser entitlement 的生产环境远程检查能力。


核心内容

很多 App 会把网页当成界面的一部分。它可能是一段 CSS 写的 UI,也可能是 JavaScript 写的业务页面,还可能是一个完整的浏览器。WKWebView 就是这类 App 和 Web 内容之间的桥。

这场 session 先给出边界:如果只是想在 App 里放一个接近浏览器的页面,并且不需要深度定制,应该优先用 SFSafariViewController。如果项目还在用已经废弃的 UIWebView,现在要迁移到更快、更响应的 WKWebView,因为 UIWebView 会在未来版本移除。

iOS 16 和 iPadOS 16 的变化集中在六件事。前三件提升 App 与页面的交互:JavaScript 可以把 HTML 元素全屏,网页可以按最小、最大、动态视口尺寸排版,用户可以用熟悉的查找 UI 搜索页面文字。第四件让内容屏蔽规则能看当前 iframe 的 URL。最后两件覆盖媒体和调试:iPadOS 的 WKWebView 支持 Encrypted Media Extensions 与 Media Source Extensions,带 web-browser entitlement 的 App 可以用 Safari Remote Web Inspector 调试生产环境网页。

这些能力都服务同一个场景:App 不再只是“嵌入网页”,还要让网页像原生界面一样参与全屏、布局、查找、过滤、播放和调试流程。

详细内容

让网页元素进入全屏

02:26)浏览器里常见的全屏 API 来到 WKWebView。视频或 canvas 游戏这类 HTML 元素,可以由 JavaScript 请求进入全屏。App 侧要先打开 WKPreferences.isElementFullscreenEnabled

webView.configuration.preferences.isElementFullscreenEnabled = true

webView.loadHTMLString("""
<script>
    button.addEventListener('click', () => {
        canvas.webkitRequestFullscreen()
    }, false);
</script>

""", baseURL:nil)

let observation = webView.observe(\.fullscreenState, options: [.new]) { object, change in
    print("fullscreenState: \(object.fullscreenState)")
}

关键点:

  • isElementFullscreenEnabled = true:允许页面里的元素使用全屏 API。
  • button.addEventListener('click', ...):示例把全屏请求绑定到用户点击事件。
  • canvas.webkitRequestFullscreen():页面中的 canvas 元素请求进入全屏。
  • webView.observe(\.fullscreenState, ...):App 观察 WKWebView 的全屏状态变化。
  • print("fullscreenState: ..."):状态变化可以驱动自定义过渡动画或界面同步。

如果你的 App 里有视频播放器、WebGL 画布、远程桌面或游戏界面,这个开关能减少原生层和 Web 层之间的手写桥接。

把动态视口范围提前告诉 WebKit

03:50)iOS 16 支持 svhlvhdvh 等 CSS 视口单位。它们分别对应较小、较大和动态变化的视口高度。Safari 底部工具栏显示和收起时,页面可用高度会变化,这些单位就是为这种布局准备的。

WKWebView 场景里,如果 App 自己会改变 WebView 的可见范围,就要提前告诉 WebKit 这个范围的上下限。

let minimum = UIEdgeInsets(top: 0, left: 0, bottom: 30, right: 0)
let maximum = UIEdgeInsets(top: 0, left: 0, bottom: 200, right: 0)
webView.setMinimumViewportInset(minimum, maximumViewportInset: maximum)

关键点:

  • minimum:声明页面可遇到的最小 viewport inset。
  • maximum:声明页面可遇到的最大 viewport inset。
  • bottom: 30bottom: 200:示例用底部 inset 表达底部控件收起和展开时的高度差。
  • setMinimumViewportInset:把范围传给 WebKit,让页面里的动态视口单位有正确的输入。

适合这个 API 的场景包括:底部工具栏会折叠的阅读器、自定义浏览器、带可拖动控制面板的 Web App 容器。

给 WKWebView 加上系统查找 UI

04:17)很多 WKWebView App 会加载长文本。用户自然会按 Command-F 或寻找页面内搜索入口。iOS 16 的 WKWebView 支持 Find interactions,App 只需要打开一个属性。

webView.findInteractionEnabled = true

if let interaction = webView.findInteraction {
  interaction.presentFindNavigator(showingReplace:false)
}

关键点:

  • findInteractionEnabled = true:启用 WKWebView 的查找交互。
  • webView.findInteraction:取得底层 UIFindInteraction 对象。
  • presentFindNavigator(showingReplace:false):由 App 主动展示查找面板。
  • showingReplace:false:示例只打开查找,不展示替换界面。

打开后,用户可以使用熟悉的 UI 和 Command-F 快捷键搜索当前页面。App 也可以通过 UIFindInteraction 展示、关闭查找面板,或用程序控制结果跳转。

只屏蔽特定 iframe 里的请求

05:46WKContentRuleList 原来可以根据请求 URL 和 top-frame URL 做匹配。问题出现在嵌入内容上:同一个页面里可能有多个 iframe,开发者有时只想让规则作用在某个 iframe 内部。

iOS 16 新增 if-frame-url。规则可以匹配发起请求的当前 frame URL。视频里的例子是在示例页面中嵌入 Wikipedia iframe,然后只屏蔽 Wikipedia frame 里的图片。

let json = """
[{
    "action":{"type":"block"},
    "trigger":{
        "resource-type":["image"],
        "url-filter":".*",
        "if-frame-url":["https?://([^/]*\\\\.)wikipedia.org/"]
    }
}]
"""

WKContentRuleListStore.default().compileContentRuleList(forIdentifier: "example_blocker",
    encodedContentRuleList: json) { list, error in
    guard let list = list else { return }
    let configuration = WKWebViewConfiguration()
    configuration.userContentController.add(list)
}

关键点:

  • "action":{"type":"block"}:规则命中后阻止资源加载。
  • "resource-type":["image"]:规则只针对图片资源。
  • "url-filter":".*":请求 URL 本身全部匹配。
  • "if-frame-url":新增条件,限制规则只在匹配的 frame 中生效。
  • wikipedia.org 正则:示例把规则限定在 Wikipedia iframe 内。
  • compileContentRuleList:把 JSON 编译为 WKContentRuleList
  • configuration.userContentController.add(list):把规则安装到 WKWebView 配置上。

这个能力适合做更细粒度的企业内容过滤、内嵌文档安全策略、以及针对第三方 iframe 的资源控制。

iPadOS 的加密媒体与生产环境检查

06:33)iPadOS 16 的 WKWebView 支持 Encrypted Media Extensions(EME)和 Media Source Extensions(MSE)。如果你的内容已经依赖这些 Web API,iPadOS App 里的 WKWebView 可以播放这类受保护媒体,效果与 macOS 上一致。session 举的例子是 Apple TV+ 这样的 premium content。

06:57)Remote Web Inspector 对带 web-browser entitlement 的 App 生效,不需要新增代码。开启流程和 Safari 一样:先在 iOS 设备的 Safari 设置里打开 Web Inspector,再在 Mac Safari 的 Advanced Settings 中启用 Develop 菜单,连接设备后从 Develop 菜单选择目标页面。

关键点:

  • EME 与 MSE 是网页已有的媒体 API,session 没有要求 App 侧新增 WKWebView 代码。
  • Remote Web Inspector 可检查 DOM、运行和调试 JavaScript、查看页面加载时间线。
  • 这个调试能力面向生产 App 中的 Web 内容,前提是 App 拥有 web-browser entitlement。

核心启发

  • 做一个全屏 Web 游戏容器:把游戏画面放在 canvas 中,App 侧开启 isElementFullscreenEnabled,Web 侧在用户点击开始游戏时调用 webkitRequestFullscreen(),再用 fullscreenState 同步原生按钮和状态栏。

  • 做一个带可收起工具栏的阅读器:底部批注栏展开时占用更多高度,收起时释放空间。用 setMinimumViewportInset 声明两个边界,让文章页里的 svhlvhdvh 布局跟随真实可视区域。

  • 做一个内置文档搜索入口:知识库、协议、帮助中心这类长文本页面,打开 findInteractionEnabled,并在原生导航栏放一个搜索按钮调用 presentFindNavigator(showingReplace:false)

  • 做一个 iframe 级内容过滤器:内嵌第三方页面时,用 if-frame-url 把图片、脚本或其他资源规则限制在指定 iframe 内,避免误伤主页面和其他嵌入内容。

  • 做生产 Web 内容排障流程:如果你的 App 符合浏览器类场景并拥有 web-browser entitlement,把 Remote Web Inspector 纳入客服和 QA 流程,用 Safari 的 Develop 菜单直接检查用户路径里的 DOM、JavaScript 和加载时间线。

关联 Session

评论

GitHub Issues · utterances