10.4 C
New York
Thursday, April 10, 2025

safari – iOS WKWebView’s addUserScript doesn’t work first time for “about:clean”


I’m able to show my difficulty utilizing the beneath easy instance.

I principally want to make use of the addUserScript to load completely different scripts based mostly upon which web site the net view has navigated to. This works advantageous for all web sites nevertheless it would not work for about:clean.

For instance, beneath works advantageous for hackerNews (“https://information.ycombinator.com”) however fails for homePage (“about:clean”):

import UIKit
import WebKit
import SnapKit

extension String {
    static let hackerNews = "https://information.ycombinator.com"
    static let homePage = "about:clean"
}

class ViewController: UIViewController, WKScriptMessageHandler, WKNavigationDelegate {
        
    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
        let configuration = WKWebViewConfiguration()
        configuration.mediaTypesRequiringUserActionForPlayback = .all
        
        let browser = WKWebView(body: .zero, configuration: configuration)
        browser.isInspectable =  true
        browser.navigationDelegate = self
        
        view.addSubview(browser)
        browser.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        browser.load(URLRequest(url: URL(string: .homePage)!))
        
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void) {
        
        guard let urlString = navigationAction.request.url?.absoluteString else {
            return
        }
        
        print("Navigating to url: (urlString)")
        webView.configuration.userContentController.removeAllUserScripts()
        webView.configuration.userContentController.removeAllScriptMessageHandlers()
        webView.configuration.userContentController.removeAllContentRuleLists()
        
        let world = WKContentWorld.world(title: "MyWorld")
        webView.configuration.userContentController.add(self, contentWorld: world, title: "handleConsoleLog")
        
        let userScript = """

perform logConsole(err) {
    console.log(`logConsole: ${err}`);
    if (window.webkit) {
        window.webkit.messageHandlers.handleConsoleLog.postMessage(err.toString());
    }
}

logConsole(`Whats up: ${window.location}`);

"""
        
        webView.configuration.userContentController.addUserScript(WKUserScript(supply: userScript, injectionTime: .atDocumentStart, forMainFrameOnly: false, in: world))
        
        decisionHandler(.enable)
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print("userContentController: (message.title), ((message.physique as? String)?.prefix(100))...")
    }

}

The above instance doesn’t name my handler on first web page load.

But when I alter .homePage within the line:

browser.load(URLRequest(url: URL(string: .homePage)!))

to make use of .hackerNews, then it really works even on first web page load.

If I exploit macOS Safari develop menu’s inspector’s console tab and “reload” the web page, then it really works too:

enter image description here

It solely would not work on “about:clean” on first web page load.

How can I get it to work?

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles