Skip to content

Instantly share code, notes, and snippets.

@rodrigo-lima
Last active June 7, 2016 01:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rodrigo-lima/b6e5b13845bfe538047c80b41558dea8 to your computer and use it in GitHub Desktop.
Save rodrigo-lima/b6e5b13845bfe538047c80b41558dea8 to your computer and use it in GitHub Desktop.

Using WKWebView

###JSHelper.swift

/// ---------------------------------------------------------------------------
// MARK:- JSScript

struct JSScript {
    var scriptName:String
    var scriptExtension:String
    var scriptContent:String
    var scriptInjectionTime:WKUserScriptInjectionTime
    var scriptLoaded = false
    
    init(_ name:String, _ ext:String = "js", _ injectionTime:WKUserScriptInjectionTime = .AtDocumentStart) {
        self.scriptName = name
        self.scriptExtension = ext
        self.scriptInjectionTime = injectionTime
        self.scriptContent = ""
    }
    
    mutating func loadIfNeeded() {
        guard !scriptLoaded else { return }
        
        var content:String? = nil
        if let jsPath = NSBundle.mainBundle().pathForResource("helper_js/\(scriptName)", ofType: scriptExtension) {
            content = try? String(contentsOfFile: jsPath, encoding: NSUTF8StringEncoding)
        }
        scriptContent = content ?? ""
    }
}

/// ---------------------------------------------------------------------------
// MARK:- JSScriptLoader

struct JSScriptLoader {
    private static let allJS:[JSScript] = [
        JSScript("UtilsAPI"),
        JSScript("ConfigAPI") // etc etc...
    ]

    static func loadAndInjectAllJS(controller:WKUserContentController) {
        for script in allJS {
            loadSingleScript(script, controller: controller)
        }
    }
    
    static func loadSingleScript(var script:JSScript, controller:WKUserContentController) {
        script.loadIfNeeded()
        injectScriptContent(script.scriptContent, injectionTime:script.scriptInjectionTime, controller:controller)
    }
    
    static func injectScriptContent(content:String, injectionTime:WKUserScriptInjectionTime, controller:WKUserContentController) {
        // by default, let's make it available on all frames
        let userScript = WKUserScript(source:content, injectionTime:injectionTime, forMainFrameOnly:true)
        controller.addUserScript(userScript)
    }
}

###Somewhere in your VC

class MyViewController: UIViewController
    var wkWebView:WKWebView?
    var webConfig:WKWebViewConfiguration {
        get {
            // Create WKWebViewConfiguration instance
            let webCfg:WKWebViewConfiguration = WKWebViewConfiguration()
            let wkController = WKUserContentController()
            wkController.addScriptMessageHandler(self, name: "ScriptHandler")
            JSScriptLoader.loadAndInjectAllJS(wkController)

            // Configure WKWebViewConfiguration instance
            webCfg.userContentController = wkController;
            return webCfg;
        }
    }
    // ... etc etc ...
}

// ---------------------------------------------------------------------------
// MARK:- WKScriptMessageHandler

extension MyViewController : WKScriptMessageHandler {
    func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
        // is this for me???
        guard message.name == "ScriptHandler", let body = message.body as? NSDictionary else { return }

        // console.log ?
        if let msg = body["logData"] as? String {
            print(msg)
            return
        }

        // other stuff....
    }
}

###UtilsAPI.js

 if (typeof(window.webkit) != 'undefined' && typeof(window._console) == 'undefined') {
     console.log("ADDING CONSOLE_LOG HELPER");
     window._console = window.console;
     window.console = {
         log: function() {
             var args = Array.prototype.slice.call(arguments);
             args = args.join(',')
             // this is where the magic happens
             window.webkit.messageHandlers.ScriptHandler.postMessage({logData: args});
             window._console.log(">>>> ARGS: " + args);
         }
     }
 }

 // window.onabort = function (msg, url, line) {
 //     window.console.log("Caught[via window.onerror]: '" + msg + "' from " + url + ":" + line);
 //     return true; // same as preventDefault
 // };

 window.onabort = function() {
     window.console.log("Caught[via window.onabort]: ...  ");
     return true; // same as preventDefault
 }

 window.onerror = function(msg, url, line, column, errorObj) {
     window.console.log("Caught[via window.onerror]: '" + msg + "' from " + url + ":" + line + ":" + column);
     return true; // same as preventDefault
 };

 window.addEventListener('error', function (evt) {
     window.console.log("Caught[via 'error' event]:  '" + evt.message + "' from " + evt.filename + ":" + evt.lineno);
     // window.console.log(evt.err, evr.name);
     evt.preventDefault();
 });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment