2

I'm a bit of a newbie to Swift programming, and may be using some construct that is making a value immutable after it is set once. I have a WKWebView that is running a JavaScript webapp, and in that JS a URL is being called like this:

var url = 'testscheme://x-callback/test?unique=' + new Date().getTime() + 'Z';
window.location = url;
Ext.toast(url, 30000);

which in turn fires the extension below in my Swift code. Trouble is, the first time the extension is called, it has the correct URL that came from the JS; but after that it seems that the first URL is "stuck" somehow and anytime it is called again, it continues to print the first URL values instead of values from any subsequent calls which have different information in them.

extension VCWebView: WKURLSchemeHandler {
    // any requests for a URL scheme should arrive here
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        print("In WKURLSchemeHandler webView()")
        print("url absolute string requested: " + (urlSchemeTask.request.url?.absoluteString ?? "{nil}"))
        // THE LINE above is where it should be printing a unique value every time it is run,
        // but gets stuck with the value from the first time it was run
    }

    // not used
    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
    }

}

I know that the JS is sending unique information, because when I close the app, and start it again, it again has a unique value the first time, but then continues to show that first unique value any time it is run again after that. There are some log file entries that I do not understand (the 4 at 09:42:01 after the second attempt):

testscheme url scheme registered
in VCWebView.swift viewDidLoad()
{1ST ATTEMPT}
09:41:12.904692-0700 MyApp[51948:6316047] [ProcessSwapping] 0x10a1842c0 - ProvisionalPageProxy::ProvisionalPageProxy: pageID = 6 navigationID = 4 suspendedPage: 0x0
In WKURLSchemeHandler webView()
url absolute string requested: testscheme://x-callback/test?unique=1570293672897Z {THIS IS WHAT JS SENT: ...897Z so this one is correct}
{2ND ATTEMPT}
09:42:01.516773-0700 MyApp[51948:6316047] [ProcessSwapping] 0x10a1842c0 - ProvisionalPageProxy::didFailProvisionalLoadForFrame: pageID = 6, frameID = 1, navigationID = 4
09:42:01.520345-0700 MyApp[51948:6316047] [ProcessSwapping] 0x10a184420 - ProvisionalPageProxy::ProvisionalPageProxy: pageID = 6 navigationID = 5 suspendedPage: 0x0
09:42:01.632990-0700 MyApp[51948:6316047] [ProcessSuspension] 0x10a1f72d0 - ProcessAssertion::processAssertionWasInvalidated()
09:42:01.633186-0700 MyApp[51948:6316047] [ProcessSuspension] 0x10a1f7f00 - ProcessAssertion::processAssertionWasInvalidated()
In WKURLSchemeHandler webView()
url absolute string requested: testscheme://x-callback/test?unique=1570293672897Z {THIS IS WHAT JS SENT: ...512Z}
09:42:31.520976-0700 MyApp[51948:6316047] [assertion] Error acquiring assertion: <NSError: 0x600002efdcb0; domain: RBSAssertionErrorDomain; code: 2; reason: "Specified target process does not exist">
09:42:31.521453-0700 MyApp[51948:6316047] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service

Those log file entries probably explain why it is failing, but I do not know how to fix it. Any ideas what I am doing wrong?

WagsMax
  • 35
  • 6
  • Were you able to figure out what happened? @WagsMax I have the same issue :( – DesperateLearner Dec 24 '19 at 21:59
  • Yes, but I could not figure out why iOS is doing this. See the hack in the code below: – WagsMax Dec 30 '19 at 18:28
  • @WagsMax, does this issue have a proper fix now? I am experiencing the same issue with `urlSchemeTask.request.url` always returning the old/first value. – Zerosero Nov 29 '22 at 03:08
  • @Zerosero, not that I know of. I haven't fiddled with the code in a while because it works at this point, and, you know, if it ain't broke don't fix it kind of thing. – WagsMax Nov 30 '22 at 17:12

2 Answers2

1

I was running into this too. It appears that the calls to didReceive to communicate back to the WebView are required, followed by a call to didFinish: https://developer.apple.com/documentation/webkit/wkurlschemetask/2890839-didreceive

After implementing these functions, my method is now called with updated parameters each time.

There's a nice example of how you might set these parameters in this post: How to intercept a WKWebView request to detect which local resource files (css, js, png, ...) load together with a HTML file?

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34327935) – emma ray May 06 '23 at 18:21
0

This is the hack that I came up with that seems to work (it's so ugly - but I could not find any other way to make this work):

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    // saving the URL string that comes in here, because it is garbled when it comes into the "start urlSchemeTask" above
    let defaults = UserDefaults.standard
    defaults.set((navigationAction.request.url?.absoluteString ?? "{nil}"), forKey: defaultsKeys.keyTwo) // save the url string
    print("1. *** url was saved")
    //decisionHandler(.cancel)
    decisionHandler(.allow) // always allow everything (in this use case)
}

func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
    var urlschemestr = ""
    urlschemestr = (urlSchemeTask.request.url?.absoluteString ?? "{nil}")
    print("2. *** url rqstd: " + urlschemestr.prefix(20) + "..." + urlschemestr.suffix(50))
    // the first time this function runs, this URL is correct, the 2nd and subsequent times, the first URL is stuck in there, so came up with a hack:
    // the decidePolicyFor (above) runs FIRST and ALWAYS seems to have the correct URL, so we save it there and use it here
    // so, get the saved url from there:
    let defaults = UserDefaults.standard
    urlschemestr = defaults.string(forKey: defaultsKeys.keyTwo)!
    print("2. *** url from saved: " + urlschemestr.prefix(20) + "..." + urlschemestr.suffix(50))
    let urlschemeurl = URL(string: urlschemestr)

    // now you can use variabe urlschemestr and urlschemeurl as needed ...
}
WagsMax
  • 35
  • 6