gpt4 book ai didi

ios - 通过 JavaScript 事件观察 WKWebView URL 更改的问题

转载 作者:行者123 更新时间:2023-12-01 15:55:13 25 4
gpt4 key购买 nike

我有一个显示 Laravel 的 WKWebView Web应用程序。我目前有我的 ViewController 设置来捕捉 URL 变化——它捕捉到了大部分变化。但是,WKWebView 似乎忽略了通过 JavaScript 事件进行的少量 URL 更改。

我已经尝试了以下所有解决方案并在下面的代码中实现了它们:

  • How to detect hash changes in WKWebView?
  • How can I detect when url of amp page changed with WKWebview
  • WKWebView function for detecting if the URL has changed
  • How can I detect when url of amp page changed with WKWebview
  • using KVO to observe WKWebView's URL property not work in iOS 10

  • 在我展示代码之前有一个有趣的说明:它能够检测到简单的#hash 更改,但无法检测从第 1 页加载到第 2 页的 JavaScript 事件操作(这是我试图捕捉的 URL 更改):
    https://myweb.com/dashboardhttps://myweb.com/dashboard/projects/new
    ViewController.swift
    import UIKit
    import WebKit

    class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    @IBOutlet var webView: WKWebView!

    override func viewDidLoad() {
    super.viewDidLoad()

    webView.navigationDelegate = self
    webView.uiDelegate = self

    webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.url), options: .new, context: nil)

    webView.load(URLRequest(url: URL(string: "https://myweb.com/")!))
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if object as AnyObject? === webView && keyPath == "URL" {
    print("URL Change 1:", webView.url?.absoluteString ?? "No value provided")
    }
    if keyPath == #keyPath(WKWebView.url) {
    print("URL Change 2:", self.webView.url?.absoluteString ?? "# No value provided")
    }
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let webURL = webView.url?.absoluteString
    let reqURL = navigationAction.request.url?.absoluteString
    print("webURL:", webURL)
    print("reqURL:", reqURL)
    decisionHandler(.allow)
    }

    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    let webURL = webView.url?.absoluteString
    print("webURL:", webURL)
    }
    }

    有一段代码似乎在 JavaScript 事件操作上触发,那就是 keyPath == #keyPath(WKWebView.url) .

    然而,它似乎只是触发了它,以及它的结果打印到控制台: URL Change 2: # No value provided (由于 nil 合并运算符: self.webView.url?.absoluteString ?? "# No value provided"

    意思是,这 2 行观察者代码是唯一能捕捉到这个变化的东西,但不返回那个变化的值:
    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.url), options: .new, context: nil)
    if keyPath == #keyPath(WKWebView.url) {
    print("URL Change 2:", self.webView.url?.absoluteString ?? "# No value provided")
    }

    任何其他尝试检索此更改的值或强制解包它都会导致在 didStartProvisionalNavigation 之后立即启动时崩溃。叫做:

    Xcode 错误
    Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
    Xcode 控制台日志
    Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/me/Apps/MyWeb/iOS/MyWeb/ViewController.swift, line 125
    2020-02-11 12:47:55.169765-0500 MyWeb[3066:124221] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/me/Apps/MyWeb/iOS/MyWeb/ViewController.swift, line 125
    (lldb)

    Xcode Error & Console Log

    我如何能够输出该 URL 更改的值?同样,当我单击 JS 按钮加载页面时,它似乎是唯一触发的代码(或者至少,控制台是这样说的)。在 Safari 中,对于 iOS 和 MacOS,URL 更改似乎确实反射(reflect)在 URL 搜索栏中;因此,我不认为这是与基于 Web 的代码(即框架、URL 欺骗)有关的问题。

    但是,我无法确认这一点,因为它是基于 Web 的 PHP/JS 脚本。

    编辑

    看来,当第一次加载 https://myweb.com在 WKWebView 中,代码也没有检测到初始重定向到 https://myweb.com/dashboard .只有上面提到的两条观察线似乎检测到了这种重定向。

    编辑 2

    我可以使用 observerValue 函数代码将确切的 URL 值打印到控制台:
    if let key = change?[NSKeyValueChangeKey.newKey] {
    print("URL: \(key)") // url value
    }

    但是,我无法将其转换为字符串、将值分配给变量或将其传递给另一个函数。如果它 .contains("https://"),有什么方法可以将此键设置为变量? ?启动时,键值 = 0 ,但在那之后,值 = 所需的 URL( https://myweb.com/dashboardhttps://myweb.com/dashboard/project/new )。

    此解决方案使用较旧的 KVO 方法来实现与 @Rudedog 相同的结果,但有更多的包袱(即,您仍然需要删除观察者并处理独立的关键路径)。有关更现代的解决方案,请参阅下面的@Rudedog 答案。

    编辑 3(KVO 解决方案)

    我能够分配 KVO WKWebView.url到一个字符串变量。从那里,我能够将字符串值传递给一个函数,然后处理我正在寻找的每个输出:
    var cURL = ""

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if let key = change?[NSKeyValueChangeKey.newKey] {
    cURL = "\(key)" // Assign key-value to String
    print("cURL:", cURL) // Print key-value
    cURLChange(url: cURL) // Pass key-value to function
    }
    }

    func cURLChange(url: String) {
    if cURL.contains("/projects/new") {
    print("User launched new project view")
    // Do something
    } else {
    // Do something else
    }
    }

    最佳答案

    在你走得更远之前,我强烈建议你使用现代的 Swift 观察方法:

    var webViewURLObserver: NSKeyValueObservation?

    override func viewDidLoad() {
    // ...
    webViewURLObserver = webview.observe(\.url, options: .new) { webview, change in
    print("URL: \(String(describing: change.newValue))")
    // The webview parameter is the webview whose url changed
    // The change parameter is a NSKeyvalueObservedChange
    // n.b.: you don't have to deregister the observation;
    // this is handled automatically when webViewURLObserver is dealloced.
    }
    }
    这样做可以使您的代码在调试问题时更加简洁和易于推理。

    关于ios - 通过 JavaScript 事件观察 WKWebView URL 更改的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60175052/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com