What's new in WKWebView
Media & Web 进阶 20m

WKWebView 的新变化

What's new in WKWebView

2022年6月6日

在 Apple 官方观看视频

一句话判断

全屏 API、查找交互、iframe 级内容屏蔽和 iPad 加密媒体——WKWebView 正在补齐与 Safari 之间的能力差距。

这场 Session 讲了什么

WKWebView 在 iOS 16 和 iPadOS 16 中获得了四类新能力:

与 Web 内容交互的新方式

  • 全屏 API:JavaScript 可以将 HTML 元素(如视频、Canvas 游戏)全屏展示。只需设置 isElementFullscreenEnabled = true,就可以通过 webkitRequestFullscreen() 触发。支持观察 fullscreenState 来自定义过渡动画。
  • CSS 视口单位:新增 svh/lvh/dvh 等动态视口单位,让 Web 内容能根据浏览器 UI 的显示/隐藏来调整布局。通过 setMinimumViewportInset 告知 WebKit 视口大小范围。
  • 查找交互(Find Interaction):设置 findInteractionEnabled = true 就能启用 Cmd+F 搜索,用户可以在页面内查找文本。

内容屏蔽增强:WKContentRuleList 新增 if-frame-url 规则,可以针对特定 iframe 中的请求应用屏蔽规则。之前只能按请求 URL 和顶级框架 URL 过滤,现在可以精确到 iframe 级别。

iPad 上的加密媒体:支持 Encrypted Media Extensions (EME) 和 Media Source Extensions (MSE),让 DRM 保护的内容(如 AppleTV+)可以在 iPad 上的 WKWebView 中播放。

远程 Web Inspector:拥有 web-browser 权限的应用可以直接用 Safari 的远程调试工具调试生产环境中的 Web 内容。

值得深挖的点

全屏 API 的实际意义比你想象的大。之前在 WKWebView 中播放视频或运行 Canvas 游戏,用户只能在应用给定的视口内操作。现在 JavaScript 可以请求真正的全屏模式,视频播放和 Web 游戏在 iOS 应用中的体验会大幅提升。fullscreenState 的 KVO 观察让你能在全屏切换时同步调整原生 UI。

if-frame-url 的精确屏蔽解决了内容屏蔽的一个重要痛点。之前你只能按”请求的 URL”和”页面顶层 URL”来决定是否屏蔽。但很多场景需要”只屏蔽某个 iframe 内的图片请求”。新 API 让规则粒度从”页面级”细化到了”iframe 级”。

Find Interaction 的一行代码启用是典型的”早该有的功能”。设置 findInteractionEnabled = true 后,用户就能用 Cmd+F 搜索页面文字。你还可以通过 findInteraction 属性编程控制查找面板的显示和导航。

代码片段

启用全屏 API:

// 开启全屏支持
webView.configuration.preferences.isElementFullscreenEnabled = true

// 加载使用全屏 API 的网页
// JavaScript: element.webkitRequestFullscreen()

// 观察全屏状态变化
let observation = webView.observe(\.fullscreenState, options: [.new]) { object, _ in
    switch object.fullscreenState {
    case .inFullscreen:
        print("进入全屏")
    case .notInFullscreen:
        print("退出全屏")
    default:
        break
    }
}

设置动态视口范围:

// 告知 WebKit 视口的最小和最大 inset
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)
// Web 内容可以用 svh/dvh/lvh 单位适配这些变化

启用查找交互:

// 一行代码开启页面内搜索
webView.findInteractionEnabled = true

// 也可以编程控制
if let interaction = webView.findInteraction {
    interaction.presentFindNavigator(showingReplace: false)
    // 或跳到下一个/上一个结果
    interaction.nextMatch()
    interaction.previousMatch()
}

iframe 级内容屏蔽:

let json = """
[{
    "action": {"type": "block"},
    "trigger": {
        "resource-type": ["image"],
        "url-filter": ".*",
        "if-frame-url": ["https?://([^/]*\\\\.)wikipedia.org/"]
    }
}]
"""
// 编译并应用规则
let ruleList = try await WKContentRuleListStore.default()
    .compileContentRuleList(forIdentifier: "blockWikiImages",
                           encodedContentRuleList: json)
webView.configuration.userContentController.addContentRuleList(ruleList!)

最佳实践

  • 用 SFSafariViewController 做简单浏览:不需要深度定制就用 SFSafariViewController,更省事
  • UIWebView 必须迁移:已标记为 deprecated,未来版本会被移除
  • 全屏 API 适合视频和游戏:文字为主的页面不需要开启
  • 视口 inset 要提前设置:在加载内容之前调用 setMinimumViewportInset
  • 内容屏蔽规则编译后复用:不要每次都重新编译,存到 WKContentRuleListStore 中

还有什么值得关注

  • 加密媒体支持让 iPad 上的 WKWebView 可以播放 DRM 内容,与 macOS 持平
  • 远程 Web Inspector 对第三方浏览器应用很有价值,可以直接调试 iOS 上的生产环境页面
  • Session 建议搭配 “What’s new in Safari Web Extensions” 和 “What’s new in Safari and WebKit” 一起看
  • 如果 WKWebView 缺少你需要的功能,通过 Feedback Assistant 提交需求,Apple 团队会据此排优先级
WWDC 2022