3

I am implementing wkwebview in an app that was using UIWebView. I am unable to get javascript to execute when pointing to a local html file that has the javascript embedded within it. The javascript is stripped to do a simple alert and load a basic google map. None of that is getting executed. Do I need to run a local server? GCDWebserver..

I should add, the html/javascript works in safari, google browser no problem.

Solutions attempted include: 1. AppTransportSecuritySettings AllowArbitrary loads. 2. ViewController.swift webview.configuration.preferences.javaScriptEnabled = true 3. This question addresses the issue and says is was fixed in iOS 10.3 Load Javascript files through HTML file on WKWebView in iOS The simulator is running 12.1 4. This question also addresses the issue with an answer of requiring GCDWebserver to be able to execute javascript using wkwebview. WKWebView not executing any js code This however was also solved in a laster version of iOS. Here is some code:

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    //@IBOutlet var googleMap: WKWebView!
    var webview: WKWebView!

     override func loadView() {
         webview = WKWebView()
         webview.navigationDelegate = self
         view = webview
     }
    override func viewDidLoad() {
        super.viewDidLoad()
        //let url = URL(string: "https://schallerf1.com")!
        let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!
        webview.load(URLRequest(url: url))
        webview.allowsBackForwardNavigationGestures = true
        let request = URLRequest(url: url)
        webview.configuration.preferences.javaScriptEnabled = true
        webview.load(request)
    }
}
<!DOCTYPE html>
<html>
    <head>
        <title>Simple Map</title>
        <meta name="viewport" content="initial-scale=1.0">
            <meta charset="utf-8">
                <style>
                    /* Always set the map height explicitly to define the size of the div
                     * element that contains the map. */
                #map {
                    height: 100%;
                }
                /* Optional: Makes the sample page fill the window. */
                html, body {
                    height: 100%;
                    margin: 0;
                    padding: 0;
                }
                </style>
                </head>
    <body>
        <b>WHYYYYYYYYYY!!!!</b>
        <div style="height:100%;width:100%;" id="map"></div>
        <script type="text/javascript">
            var name = "TESTTESTTEST";
            alert('code: '    + name + '\n');
            var map;
            function initMap() {
                map = new google.maps.Map(document.getElementById('map'), {
                                          center: {lat: 39.976068, lng: -83.003297},
                                          zoom: 8
                                          });
            }
        </script>
        <script async defer src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxxxxxxxxxx&callback=initMap"></script>
    </body>
</html>

None of the javascript works, I should get an alert and a simple google map should display. Do I need to look into the local web server GCDWebserver?

1 Answer 1

0

You should be calling your javascript in this WKNavigationDelegate method, which is called when the webview finishes loading.

public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("initMap()", completionHandler: { (value, err) in
        // Handle response here.
    })
}

Also, I'm not sure why you're calling two different webview.load() requests - maybe don't do that?

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you Jake for taking the time to answer. I implemented the WkNavigationDelegate as suggested. Still do not appear to be executing javascript. My index.html file does a window.load on main.html. Thus the initMap() function is not found from main.html. I added a test function into index.html with an alert alert('code:' + name + ' \n') and a console.log console.log("i should see this in the console");, but they are not getting executed even though the function is found. Any thoughts?
Try printing out value and err in the completionHandler of that function above (evaluateJavaScript). What does it say?
Hi Jake. Value returns nothing, err returns nil. Here is the output from the console; Optional(Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=ReferenceError: Can't find variable: initMap, WKJavaScriptExceptionColumnNumber=8, WKJavaScriptExceptionSourceURL=file:///Users/schallerf1/Library/Developer/CoreSimulator/Devices/data/Containers/Bundle/Application/30497599-5839-4A2C-87F7-CC2D8F4F16DA/HistOrigin.app/www/index.html, NSLocalizedDescription=A JavaScript exception occurred}) nil
Key message here is "Can't find variable: initMap" - it's not finding your JS function anywhere. Make sure you're loading the correct source. Try removing the subdirectory: "www" from your resource url. Instead: Bundle.main.url(forResource: "index", withExtension: "html")!
Jake, your suggestion of eliminating the index.htm file to point directly to the main.html file is the answer to this question. Im on to the next obstacle now, but that is a new question. Thank you very much for your time and effort.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.