###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();
});