This is how you do it with WKWebView
. YourWebView
is UIView or ViewController class.
@interface YourWebView () <WKNavigationDelegate, WKScriptMessageHandler>
- (void)injectWSKitScriptInUserContentController:(WKUserContentController*)userContentController;
@end
in your implementation in -init or -initWithFrame:
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
self.autoresizesSubviews = YES;
self.wantsLayer = YES;
WKWebViewConfiguration* conf = [[WKWebViewConfiguration alloc] init];
conf.suppressesIncrementalRendering = NO;
conf.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;
WKUserContentController* userContentController = [[WKUserContentController alloc] init];
[self injectWSKitScriptInUserContentController:userContentController];
[userContentController addScriptMessageHandler:self name:@"yourscript"];
conf.userContentController = userContentController;
#ifdef DEBUG
NSLog(@"Developer Extras Enabled");
[conf.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
#endif
WKWebView *webView = [[WKWebView alloc] initWithFrame:frame configuration:conf];
webView.navigationDelegate = self;
add webView
to view or where ever you need it and define a method to inject js.
-(void)injectWSKitScriptInUserContentController:(WKUserContentController*)userContentController {
NSBundle* bundle = [NSBundle bundleForClass:[YourWebView class]];
NSString* scriptLocation = [bundle pathForResource:@"yourscript" ofType:@"js"];
NSString* scriptSource = [NSString stringWithContentsOfFile:scriptLocation encoding:NSUTF8StringEncoding error:nil];
WKUserScript* userScript = [[WKUserScript alloc] initWithSource:scriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
[userContentController addUserScript:userScript];
}
and then follow the protocols on what else to implement in YourWebView
in example something like interaction with your webview, like forward, reload, back, etc..
and finally you will want to add a javascript file as starting point to your app. "yourscript.js" mentioned above.
(function() {
"use strict";
var Events = {
listeners: { },
gc: function() {
var events = Object.keys(this.listeners)
for (var i = events.length - 1; i >= 0; i -= 1) {
var eventName = events[i],
listeners = this.listeners[eventName]
if (listeners.length === 0) {
delete this.listeners[eventName]
}
}
},
once: function(name, listener) {
if (name in this.listeners) {
this.listeners[name].push({ oneshot: true, listener: listener })
return
}
this.listeners[name] = [
{ oneshot: true, listener: listener },
]
},
on: function(name, listener) {
if (name in this.listeners) {
this.listeners[name].push({ listener: listener })
return
}
this.listeners[name] = [ { listener: listener } ]
},
off: function(name, listener) {
if ( ! (name in this.listeners)) {
return
}
var listeners = this.listeners[name]
for (var i = listeners.length - 1; i >= 0; i -= 1) {
if (listeners[i].listener === listener) {
listeners.splice(i, 1)
return
}
}
},
trigger: function(name, arg) {
if ( ! (name in this.listeners)) {
return
}
var event = { stopIteration: false, data: arg }
var listeners = this.listeners[name]
for (var i = 0; i < listeners.length; i += 1) {
var listener = listeners[i]
try {
listener.listener(event)
} catch (e) { }
if (listener.oneshot) {
listeners.splice(i, 1)
i -= 1
}
}
this.gc()
},
}
var ETimeout = new Error('WSKit: configuration timeout'),
_config = { resolve: null, reject: null, resolved: false }
window.WSKit = {
configuration: new Promise(function(resolve, reject) {
_config.resolve = resolve
_config.reject = reject
}),
addEventListener: function(name, listener, config) {
config = config || { }
if (config.oneshot) {
Events.once(name, listener)
} else {
Events.on(name, listener)
}
},
removeEventListener: function(name, listener) {
Events.off(name, listener)
},
dispatchEvent: function(name, arg) {
Events.trigger(name, arg)
},
}
setTimeout(function() {
if ( ! _config.resolved) {
_config.reject(ETimeout)
}
}, 5000)
WSKit.addEventListener('configure', function(ev) {
_config.resolve(ev.data)
})
window.webkit.messageHandlers.webscreen.postMessage('obtainconfiguration')
})();
This should pretty much work