WWDC Quick Look 💓 By SwiftGGTeam
Explore WKWebView additions

Explore WKWebView additions

元の動画を見る

ハイライト

WKWebView は、JavaScript を使用しないコンテンツ操作 API、自動 HTTPS アップグレード、WebRTC 権限制御およびダウンロード管理を追加し、アプリに埋め込まれた Web ページのエクスペリエンスをネイティブ ブラウザーのエクスペリエンスに近づけます。

主な内容

アプリ内で Web コンテンツを表示するには、開発者は次の選択を迫られます。SFSafariViewControllerまだWKWebView?前者はシンプルですが対話が制限されており、後者は柔軟性がありますが、大量の JavaScript インジェクション コードを記述する必要があります。

WWDC2021 が与えるものWKWebViewネイティブ API のバッチが追加されました。以前は JavaScript に注入する必要があった多くの処理が、Objective-C/Swift メソッドを呼び出すことで直接実行できるようになりました。これにより、ネイティブ Web ブリッジングの複雑さが軽減され、アプリバインド ドメインなどのセキュリティ機能が適切に動作できるようになります。

同時に、自動 HTTP アップグレード、HTTPS、WebRTC など、もともと Safari でのみ利用可能だった多くのブラウザレベルの機能も公開されました。getUserMedia、ファイルのダウンロード。これらにより、アプリに埋め込まれた Web ページのエクスペリエンスがフル ブラウザーのエクスペリエンスに近づきます。

##詳細

JavaScript を使用せずに Web コンテンツを操作する

JavaScript の挿入にはいくつかの問題があります。ネイティブ インターフェイスと Web インターフェイスは乱雑に記述されやすく、副作用が生じる可能性があり、アプリバインド ドメインのセキュリティ機能と互換性がありません。今年は、JavaScript を必要としない 3 つの新しい API が追加されました。

Theme Color

Webページが渡されました<meta name="theme-color">テーマの色を設定すると、アプリはそれを直接読み取ることができます。

// 读取网页主题色
if let themeColor = webView.themeColor {
    headerView.backgroundColor = themeColor
}

// 读取计算出的背景色(themeColor 未设置时可用)
if let bgColor = webView.underPageBackgroundColor {
    scrollView.backgroundColor = bgColor
}

キーポイント:

  • themeColorWebページのメタタグで設定されたテーマカラーを返す(05:51)
  • underPageBackgroundColorコンテンツの端までスクロールするときに塗りつぶしの色として使用される計算された背景色です (06:12)
  • Safari はこれら 2 つの属性を使用して、Web ページとブラウザ Chrome の視覚的な統合を実現します (06:22)
  • 書くことができますunderPageBackgroundColorスクロールエッジの色をカスタマイズする (06:28)

テキスト インタラクションを無効にする

ビデオ コンテンツでは、ユーザーが誤って再生ボタンの代わりにテキスト選択コントロールに触れてしまう可能性があります。

let preferences = WKPreferences()
preferences.textInteractionEnabled = false

let configuration = WKWebViewConfiguration()
configuration.preferences = preferences

let webView = WKWebView(frame: .zero, configuration: configuration)

キーポイント:

  • textInteractionEnabled = falseすべてのテキスト インタラクションをオフにする (07:01)
  • 文字選択、虫眼鏡、コピーメニューは表示されません。
  • メディア再生に重点を置いた Web ページのシナリオに適しています

メディア再生コントロール

以前は、メディアを一時停止するには、JavaScript を挿入して DOM を走査してビデオ/オーディオ要素を見つける必要がありました。ここで API を直接呼び出します。

// 暂停页面上所有媒体(等效于对每个 media 元素调用 pause())
webView.pauseAllMediaPlayback()

// 挂起所有媒体播放,新加载的媒体也不会自动播放
webView.setAllMediaPlaybackSuspended(true)

// 恢复媒体播放
webView.setAllMediaPlaybackSuspended(false)

// 关闭所有画中画窗口
webView.closeAllMediaPresentations()

// 查询媒体播放状态
webView.requestMediaPlaybackState { state in
    switch state {
    case .playing, .paused, .suspended:
        print(state)
    @unknown default:
        break
    }
}

キーポイント:

  • pauseAllMediaPlayback()現在のページのメディアにのみ影響します。更新後も新しいメディアは引き続き再生されます (09:37)
  • setAllMediaPlaybackSuspended(true)これは WebView レベルの設定であり、更新後も有効です (10:08)
  • 後者も、復元されるまでユーザー メディア コントロールを無効にします (07:57)
  • Web ページの DOM 構造を理解する必要はありません (09:14)

ブラウザレベルの機能

自動 HTTPS アップグレード

iOS 15 および macOS Monterey 以降、HTTPS をサポートすることが知られているサイトへの HTTP リクエストは自動的に HTTPS にアップグレードされます (12:04)。開発者が何もする必要はありません。

オフにする必要がある場合 (ローカル デバッグなど):

let configuration = WKWebViewConfiguration()
configuration.upgradeKnownHostsToHTTPS = false  // 不建议用于生产环境

キーポイント:

  • デフォルトで有効になっており、設定は必要ありません (12:17)
  • HTTPS をサポートすることがわかっているサイトでのみ動作します (12:07)
  • シャットダウン フラグは実稼働コードに表示されるべきではありません (12:31)

WebRTC / getUserMedia

iOS 14.3 で WKWebView のサポートが開始getUserMedia今年はさらに改良されました:

// 自定义 scheme handler 加载时,权限提示显示 App 名称而非网站 URL
let schemeHandler = MyCustomSchemeHandler()
configuration.setURLSchemeHandler(schemeHandler, forURLScheme: "myapp")

// 控制摄像头和麦克风权限提示
class MyUIDelegate: NSObject, WKUIDelegate {
    func webView(
        _ webView: WKWebView,
        requestMediaCapturePermissionFor origin: WKSecurityOrigin,
        initiatedByFrame frame: WKFrameInfo,
        type: WKMediaCaptureType,
        decisionHandler: @escaping (WKPermissionDecision) -> Void
    ) {
        // 对信任的域名跳过二次提示
        if origin.host == "trusted.example.com" {
            decisionHandler(.grant)
        } else {
            decisionHandler(.prompt)  // 显示系统提示
        }
    }
}

webView.uiDelegate = MyUIDelegate()

キーポイント:

  • カスタム スキーム ハンドラーが読み込まれると、許可プロンプトに Web サイトの URL ではなくアプリ名が表示されます (12:54)
  • WKUIDelegateカメラ/マイクの許可を求めるプロンプトを表示する新しい制御方法 (13:15)
  • 戻る.grant直接の認可、.promptプロンプトを表示、.deny拒否 (14:01)
  • デリゲートを実装しない場合はデフォルトの動作を維持する (システム プロンプト) (13:55)

メディア キャプチャ ステータスの制御

// 关闭摄像头
webView.setCameraCaptureState(.none)

// 开启摄像头
webView.setCameraCaptureState(.active)

// 关闭麦克风
webView.setMicrophoneCaptureState(.none)

// 开启麦克风
webView.setMicrophoneCaptureState(.active)

キーポイント:

  • カメラとマイクのキャプチャ ステータスを直接制御します。JavaScript は必要ありません (15:04)
  • ステータスバーの録音インジケーターは終了後消えます(16:54)
  • 点灯後、インジケーターが再表示されます (17:02)

ダウンロード管理

WKWebView には、ダウンロード サポートと 3 つのトリガー メソッドが追加されています。

Web ページの JavaScript トリガー

// 网页中的 JavaScript
const link = document.createElement('a');
link.href = 'https://example.com/image.jpg';
link.download = 'cute-kitten.jpg';
link.click();
// App 端处理
func webView(
    _ webView: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
    if navigationAction.shouldPerformDownload {
        decisionHandler(.download)
        return
    }
    decisionHandler(.allow)
}

Content-Disposition を介してサーバーがトリガーされました

func webView(
    _ webView: WKWebView,
    decidePolicyFor navigationResponse: WKNavigationResponse,
    decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void
) {
    let headers = navigationResponse.response as? HTTPURLResponse
    if let disposition = headers?.value(forHTTPHeaderField: "Content-Disposition"),
       disposition.contains("attachment") {
        decisionHandler(.download)
        return
    }
    decisionHandler(.allow)
}

アプリによって開始

let request = URLRequest(url: URL(string: "https://example.com/file.pdf")!)
webView.startDownload(using: request) { download in
    download.delegate = self
}

ダウンロード手数料

extension ViewController: WKDownloadDelegate {
    func download(
        _ download: WKDownload,
        decideDestinationUsing response: URLResponse,
        suggestedFilename: String,
        completionHandler: @escaping (URL?) -> Void
    ) {
        let url = FileManager.default
            .urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent(suggestedFilename)
        completionHandler(url)
    }

    func download(
        _ download: WKDownload,
        didFailWithError error: Error,
        resumeData: Data?
    ) {
        // resumeData 可用于恢复下载
        if let resumeData = resumeData {
            // 保存 resumeData,稍后恢复
        }
    }
}

キーポイント:

  • 3 つのトリガー方法: Web ページ JS、サーバー ヘッダー、アプリのアクティブ コール (17:54)
  • WKDownloadデリゲートを設定する必要があります。設定しない場合、ダウンロードは自動的にキャンセルされます (19:09)
  • decideDestinationUsingファイルの保存場所を決定する (19:13)
  • 失敗時resumeData中断されたダウンロードを再開するために使用できます (19:21)

重要ポイント

  1. JavaScript インジェクションではなくネイティブ API の使用を優先しますpauseAllMediaPlaybackthemeColorAPI によりコードがより簡潔になり、アプリバインド ドメインが無効になるのを防ぎます。
  2. 使用setAllMediaPlaybackSuspended永続的なメディア制御を実行します。比較するpauseAllMediaPlaybackより徹底すると、ページを更新した後も有効になり、グローバルなミュートが必要なシナリオに適しています。
  3. WebRTC 権限の委任により、ユーザー エクスペリエンスが向上します。信頼できる自己所有のドメイン名を直接認証して、ユーザーが継続的なポップアップ ウィンドウに煩わされることを回避します。セキュリティとエクスペリエンスの両方を考慮して、他のドメイン名のプロンプトを維持します。
  4. ダウンロード管理により、コンテンツの共有が簡単になります。以前は、WKWebView はダウンロードをサポートしておらず、ユーザーはスクリーンショットを撮るか、画像を長押しして保存することしかできませんでした。ファイルのダウンロードとダウンロードの再開を完全にサポートできるようになりました。
  5. 自動 HTTPS アップグレードにより、設定の負担が軽減されます。アプリ層でプロトコルのアップグレード ロジックを実行する必要はありません。 WebKit は、HTTPS をサポートすることがわかっている Web サイトを自動的に処理します。

関連セッション

コメント

GitHub Issues · utterances