首页 > 解决方案 > 在 SwiftUI 中使用 WKWebView 时如何拦截链接导航?

问题描述

我在 SwiftUI 应用程序中使用 WKWebView。我的包中有一个 HTML 文件,我最初将其加载到 WKWebView 中。该文件中有一个链接,如果点击该链接,我想在外部浏览器中打开该链接。我使用以下代码创建了 WKWebView:

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    typealias UIViewType = WKWebView

    let request: URLRequest

    func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
        let webView = WKWebView()
        let delegate = WVNavigationDelegate()
        webView.navigationDelegate = delegate
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
        uiView.load(request)
    }
}

我使用以下代码创建了委托:

import Foundation
import WebKit

class WVNavigationDelegate: NSObject, WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        switch navigationAction.navigationType {
        case WKNavigationType.linkActivated:
            UIApplication.shared.open(navigationAction.request.url!, options: [:], completionHandler: nil)
            decisionHandler(.cancel)
        default:
            decisionHandler(.allow)
        }
    }
}

如果我注释掉创建和分配委托的行,除了在外部打开的链接外,一切正常。编译这些行后,WebView 中不会加载任何内容。我print()在委托的函数开头放了一条语句,它甚至没有被执行。我在这里做错了什么?

标签: iosswiftui

解决方案


很弱,navigationDelegate所以在提供的代码中,它会在退出时立即释放makeUIView

解决方案是将其保留为成员,如

struct WebView: UIViewRepresentable {
    typealias UIViewType = WKWebView

    let request: URLRequest
    private let delegate = WVNavigationDelegate()   // << here !!

    func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
        let webView = WKWebView()
        webView.navigationDelegate = delegate
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
        uiView.load(request)
    }
}

推荐阅读