Как перехватить навигацию по ссылкам при использовании WKWebView в SwiftUI? - PullRequest
1 голос
/ 07 мая 2020

Я использую WKWebView в приложении SwiftUI. В моем пакете есть файл 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() в начало функции в делегате, и он даже не был выполнен. Что я здесь делаю не так?

1 Ответ

0 голосов
/ 07 мая 2020

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)
    }
}
...