SwiftUI WKWebView обнаруживает изменение URL - PullRequest
0 голосов
/ 11 октября 2019

Я быстрый ученик. Я работаю с SwiftUI, который является структурой, я должен реализовать WKWebView, и в этом, URL-адрес изменяется динамически. Я должен поймать эти изменяющиеся URL, но решения, которые я пробовал, не работают.

Например: https://stackoverflow.com/a/48273950/10088243 Я попробовал этот блок кода, но он не работает, и он дает мне некоторые ошибки компилятора:

import SwiftUI
import WebKit

struct ContentView: UIViewRepresentable, WKNavigationDelegate {

    let request = URLRequest(url: URL(string: "https://apple.com")!)

    func makeUIView(context: Context) -> WKWebView  {
    let preferences = WKPreferences()
    preferences.javaScriptEnabled = true
    preferences.javaScriptCanOpenWindowsAutomatically = true

    let configuration = WKWebViewConfiguration()
    configuration.preferences = preferences
    let webView = WKWebView(frame: .zero, configuration: configuration)
    webView.allowsBackForwardNavigationGestures = true


    return webView
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
 // 'override' can only be specified on class membe
  if keyPath == #keyPath(WKWebView.url) {
    print("### URL:", self.webView.url!)
  }

  if keyPath == #keyPath(WKWebView.estimatedProgress) {
    // When page load finishes. Should work on each page reload.
    if (self.webView.estimatedProgress == 1) {
      print("### EP:", self.webView.estimatedProgress)
    }
  }
}

func updateUIView(_ uiView: WKWebView, context: Context) {
    uiView.load(request)
}

func webViewDidFinishLoad(webView : WKWebView) {
    print("Loaded: \(String(describing: webView.url))")
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    print("Loaded: \(String(describing: webView.url))")
    //progressView.isHidden = true
}

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    //progressView.isHidden = false
    print("Loaded: \(String(describing: webView.url))")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

У меня Non-class type 'ContentView' не может соответствовать ошибке протокола NSObjectProtocol протокола класса в строке struct ContentView ...

Ответы [ 3 ]

2 голосов
/ 11 октября 2019

Я нашел очень хорошее решение моего вопроса. Я опубликую это здесь. Может быть, кто-то хочет это увидеть.

observe.observation = uiView.observe(\WKWebView.url, options: .new) { view, change in
    if let url = view.url {
        // do something with your url
    }
}
2 голосов
/ 11 октября 2019

вы используете это для делегатов WKNavigationProtocol для выполнения (например, разрешения или отмены загрузки URL) вашего действия

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if let host = navigationAction.request.url?.host {
        if host.contains("facebook.com") {
            decisionHandler(.cancel)
            return
        }
    }

    decisionHandler(.allow)
}
1 голос
/ 02 ноября 2019

Вы можете использовать наблюдение ключ / значение для обнаружения изменений в свойстве url WKWebView.

Вот простой пример оборачивания WKWebView в UIViewRepresentable.

Обратите внимание, что, поскольку мыизменяя свойство, UIViewRepresentable представляет собой final class, а не структуру.

import Combine
import SwiftUI
import WebKit

final class WebView: UIViewRepresentable {

    @Published var url: URL? = nil {
        didSet {
            if url != nil {
                willChange.send(url)
            }
        }
    }

    private let view = WKWebView()

    private var urlChangedObservation: NSKeyValueObservation?
    private let willChange = PassthroughSubject<URL?, Never>()

    func makeUIView(context: Context) -> WKWebView {
        return makeWebView()
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
    }

    func display(_ html: String) {
        self.view.loadHTMLString(html, baseURL: nil)
    }

    public func load(_ url: String) -> WebView {
        let link = URL(string: url)!
        let request = URLRequest(url: link)
        self.view.load(request)
        return self
    }

    func makeWebView() -> WKWebView {
        self.urlChangedObservation = self.view.observe(\WKWebView.url, options: .new) { view, change in
            if let url = view.url {
                self.url = url
            }
        }
        return self.view
    }
}

Затем можно прослушать уведомление об изменении URL-адреса в onReceive () контейнера, содержащего WebView:

.onReceive(self.webview.$url) { url in
                    if let url = url {
                }
}
...