以前iOS和javascript交互时用的最多的方法大概是:
-(NSString*)stringByEvaluatingJavaScriptFromString:(NSString *)script;
-(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;
用iOS去执行js则用第一种方法;如果从js中获取参数,则通过UIWebView的代理方法(声明中的方法二)重定向返回NO,截取js传来的特殊URL再解析。
这样做不是不可以,只是不优雅,起码web端的兄弟如果支持Android和iOS的话,是两套代码。
以下这种方式是iOS7中的javascriptcore.framework,使用之前先倒入framework。不少资料网上也有,不赘述,只补充一个比较重要且网上没提到的方法:
- (JSValue *)valueForProperty:(NSString *)property;
真实商业项目中的js比这个Demo要复杂很多,所以基本很少会让你去直接调用function方法,而是去js的对象中调用属性方法,或者是属性的属性方法;但是无论几层属性,都是用这个方法去将属性拆解。
/*javascript code*/
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function testMethod1(test1){
alert(test1);
}
person = new Object();
document.write(person.firstName);
person.father.say = function(words){
alert(words);
}
function testMethod2(test2) {
person.father.say(test2);
}
</script>
</head>
<body style="background:#CDE; color:#FFF">
<center>
<input type="button" value="test1" onclick=testMethod1("test1")>
<input type="button" value="test2" onclick=testMethod2("test22")>
</center>
</body>
</html>
/* Object-C code*/
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
NSLog(@"contextname[%@]",self.context.name);
self.context[@"testMethod1"] = ^(NSString *test){
NSLog(@"test=[%@]",test);
};
JSValue *person = [self.context objectForKeyedSubscript:@"person"];
JSValue *fatherValue = [person valueForProperty:@"father"];
JSValue *sayValue = [fatherValue valueForProperty:@"say"];
sayValue[@"say"] = ^(NSString *test){
NSLog(@"test2=[%@]",test);
};
//下面这种方式block不会执行;
self.context[@"person.father.say"] = ^(NSString *test){
NSLog(@"test2=[%@]",test);
};
/*如果javascript代码中属性当中还有属性用下面方法依次取出
- (JSValue *)valueForProperty:(NSString *)property;
但是千万不能用context[@"person.father.say"]这种方式!!!
*/
}