WKWebview与原生的JS交互(js调用原生)
如果在js端直接使用window.webkit.messageHandlers.postMessage方法进行交互,可以是可以,不过如果js需要和安卓进行js交互的话,就需要写两套方案了。
所以,要实现js“优雅”地调用原生,需要实现3个部分:
1.js的注入脚本准备,
2.WKUserContentController的配置,
3.WKWebview的配置。
1.准备js的注入脚本。
我们要声明一个js对象,然后将交互所需的方法放到这个对象里面。
js脚本文件内容如下(实现了setTitle方法):
var jsObject = {}; //声明js交互对象
jsObject.bridge = function(name) { //js交互桥接方法
var args = new Array(arguments.length - 1);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i + 1];
}
window.webkit.messageHandlers[name].postMessage(args);
};
jsObject.setTitle = function(title){ //js实际中需要调用的方法
jsObject.bridge("setTitle",title);
};
2.配置WKUserContentController:
新建一个WKUwerContentController的子类,然后在里面实现载入UserScript的方法。
-(void)loadScript {
NSString *jsPath = [[NSBundle bundleForClass:self.class] pathForResource:@"bridge" ofType:@"js"];
if (jsPath != nil) {
NSString *jsContent = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:nil];
_userScript = [[WKUserScript alloc] initWithSource:jsContent injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
if (_userScript != nil) {
[self addUserScript:_userScript];
}
}
}
3.WKWebview的配置:
有两种方式,单独写一个遵循WKScriptMessageHandler协议的类来实现对应方法,或者直接使WKWebview遵循WKScriptMessageHandler协议。
下面的方法是使WKWebview遵循WKScriptMessageHandler协议。
添加类方法:
+(WKWebViewConfiguration *)config {
WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init];
JSUCC *ucc = [[JSUCC alloc] init];
conf.userContentController = ucc;
return conf;
}
重写init方法:
-(instancetype)init {
self = [super initWithFrame:CGRectZero configuration:[JSWKWebView config]];
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"%@",message.name);
NSArray *args = message.body;
WEAKSELF
if ([message.name isEqualToString:@"setTitle"]) {
//这里实现相应方法。
}
}
所以,要实现js“优雅”地调用原生,需要实现3个部分:
1.js的注入脚本准备,
2.WKUserContentController的配置,
3.WKWebview的配置。
1.准备js的注入脚本。
我们要声明一个js对象,然后将交互所需的方法放到这个对象里面。
js脚本文件内容如下(实现了setTitle方法):
var jsObject = {}; //声明js交互对象
jsObject.bridge = function(name) { //js交互桥接方法
var args = new Array(arguments.length - 1);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i + 1];
}
window.webkit.messageHandlers[name].postMessage(args);
};
jsObject.setTitle = function(title){ //js实际中需要调用的方法
jsObject.bridge("setTitle",title);
};
2.配置WKUserContentController:
新建一个WKUwerContentController的子类,然后在里面实现载入UserScript的方法。
-(void)loadScript {
NSString *jsPath = [[NSBundle bundleForClass:self.class] pathForResource:@"bridge" ofType:@"js"];
if (jsPath != nil) {
NSString *jsContent = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:nil];
_userScript = [[WKUserScript alloc] initWithSource:jsContent injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
if (_userScript != nil) {
[self addUserScript:_userScript];
}
}
3.WKWebview的配置:
有两种方式,单独写一个遵循WKScriptMessageHandler协议的类来实现对应方法,或者直接使WKWebview遵循WKScriptMessageHandler协议。
下面的方法是使WKWebview遵循WKScriptMessageHandler协议。
添加类方法:
+(WKWebViewConfiguration *)config {
WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init];
JSUCC *ucc = [[JSUCC alloc] init];
conf.userContentController = ucc;
return conf;
}
重写init方法:
-(instancetype)init {
self = [super initWithFrame:CGRectZero configuration:[JSWKWebView config]];
return self;
}
}
实现WKScriptMessageHandler代理方法:
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"%@",message.name);
NSArray *args = message.body;
WEAKSELF
if ([message.name isEqualToString:@"setTitle"]) {
//这里实现相应方法。
}
}
}
评论
发表评论