5

I'd like to try injecting js script to the WKWebView but it doesn't work. So it is a web but when it's loaded on the App, we should hide the header and footer. I fetch the CSS URL from the config and load it and try to inject it along with the JS written on the code. But, the web is loaded but the expected things doesn't work. What's wrong?

This is the code (I omit many of unrelated code to the question)

import UIKit
import WebKit

class CustomPageWebViewController: UIViewController, WKNavigationDelegate {

    private var webView: WKWebView = WKWebView()


    override func viewDidLoad() {
        super.viewDidLoad()

        webView.navigationDelegate = self
        view.addSubview(webView)

        // Request web page
        requestWebPage()

    }


    // MARK: - Request Web Page

    func requestWebPage() {
        if let urlString = URL(string: determineURLBasedOnPaymentName()) {
            webView.load(URLRequest(url: urlString))
        }
    }


    //

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        removeHeaderAndFooter(webView: webView)
    }

    func removeHeaderAndFooter(webView: WKWebView) {
        let cssURLString = ConfigManager.sharedInstance.cssURL
        if cssURLString != "" {
            let cssURL = URL(string: cssURLString)
            if let cssURL = cssURL {
                let sessionConfig = URLSessionConfiguration.default
                let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
                var request = URLRequest(url: cssURL)
                request.httpMethod = "GET"

                let task = session.dataTask(with: request, completionHandler: { (data: Data!, response: URLResponse!, error: Error!) -> Void in
                    if (error == nil) {
                        let result = String(data: data, encoding: String.Encoding.utf8)!

                        var js = "!function(){var e=document.createElement(\"style\");e.type=\"text/css\",e.innerHTML=window.atob(%@),document.getElementsByTagName(\"head\")[0].appendChild(e);var t=document.createElement(\"style\");t.type=\"text/css\",t.innerHTML=\"#tab-hotel,#tabs-2,.rail-order__flex{display:none;} .search__label--input{height:45px;} #tabs-2{display:block;}\",document.body.appendChild(t)}();"
                        // So after I get the CSS file from the link, I will inject it to the JS file here
                        js = String(format: js, result)

                        // And then inject the whole script to the webview
                        self.webView.evaluateJavaScript(js, completionHandler: { (any, error) in

                        })
                    }
                })
                task.resume()
            }
        }
    }
}
mrjimoy_05
  • 3,452
  • 9
  • 58
  • 95

3 Answers3

2

js message handler execution in WKWebview is handled using WKUserScript

you can execute JS by following my answer in link WKUserScript not working

this is the way we excute JS in WKWebview

[objectofWKWebView evaluateJavaScript:yourScript completionHandler:^(id result, NSError *error) {}];

you can create category of WKWebView and add function like

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script {
__block NSString *resultString = nil;
__block BOOL finished = NO;

[self evaluateJavaScript:script completionHandler:^(id result, NSError *error) {
    if (error == nil) {
        if (result != nil) {
            resultString = [NSString stringWithFormat:@"%@", result];
        }
    } else {
        NSLog(@"evaluateJavaScript error : %@", error.localizedDescription);
    }
    finished = YES;
}];

while (!finished)
{
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

return resultString;
}
Anurag Soni
  • 1,077
  • 10
  • 14
2

Swift 5:

Before Show WebSite inject css to html

import UIKit
import WebKit

class WebViewController: UIViewController, WKNavigationDelegate {

    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        config()
    }

    private func config(){

        webView.navigationDelegate = self

        guard let url = URL(string: "url") else {
            return
        }

        webView.load(URLRequest(url: url))

    }

    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        let css = "Css Code"
        let js = "var style = document.createElement('style'); style.innerHTML = '\(css)'; document.head.appendChild(style);"
        webView.evaluateJavaScript(js, completionHandler: nil)
    }


}
Mohammad Razipour
  • 3,643
  • 3
  • 29
  • 49
-7

Please use UIWebView and webView.stringByEvaluatingJavaScript(from: "")

Mayur Kothawade
  • 544
  • 4
  • 14
  • While this is a possible way, be aware that using UIWebView is in general discouraged by Apple. I am sure it will eventually be deprecated. @Anurag's answer shows the "proper" way. – Gero May 19 '17 at 13:51
  • @Gero You are correct but Apple has to improve WKWebView a lot, there are lots of things still missing in WKWebView like content window resize problem. So its better to use UIWebView unless and until we need callback like features in javascript which WKWebView supports. – Mayur Kothawade May 22 '17 at 05:04
  • 1
    Oh, of course, that's definitely true. I just wanted to point out apple's "recommendation" here for completeness. Personally I already use WKWebView wherever it works so that I eventually won't have to migrate everything at once and get in the habit of the slightly more complex setup (if you're working with JS in it, at least). – Gero May 22 '17 at 06:23