JS代用原生OC
方式一:url拦截,这里略过
注意:在iOS中拦截到的url scheme将全部转化为小写;
html中需要设置编码,否则中文参数可能会出现编码问题;
JS用打开一个iFrame的方式替代直接用document.location的方式,document.location 有一个很严重的问题,就是如果我们连续 2 次改 document.location 的话,在 delegate 方法中,只能截获后面那次请求,前一次请求由于很快被替换掉,所以被忽略掉。
方式二:通过JavaScriptCore(iOS 7之后),用来做JS交互,因此JS与原生OC交互也变得简单了许多。
//获取js上下文,及本地添加js调用方法,一般情况下都放在-(void)webViewDidFinishLoad:(UIWebView *)webView方法里。
-(void)webViewDidFinishLoad:(UIWebView *)webView{
//获取js上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//添加js代用方法
self.jsContext[@"ocGetValueFromJS"]= ^(){
NSArray *array = [JSContext currentArguments];
for (NSString *value in array) {
NSLog(@"收到js值:%@",value);
}
};
//异常处理
self.jsContext.exceptionHandler = ^(JSContext* context,JSValue *exceptionValue){
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
}
方式三:同方式二相似,通过JSExport协议
@protocol JSObjcDelegate<JSExport>
-(void)getMessage:(id)msg;
@end
@interface WebViewController ()<UIWebViewDelegate,JSObjcDelegate>
-(void)webViewDidFinishLoad:(UIWebView *)webView{
//获取js上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//设置代理
self.jsContext[@"ios"]= self;
//异常检查,当oc本地调用的js方法不存时,会打印异常信息
self.jsContext.exceptionHandler = ^(JSContext* context,JSValue *exceptionValue){
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
}
//代理方法的实现
-(void)getMessage:(id)message{
NSLog(@"getMessage-------%@",message);
}
OC调用JS
方式一
NSString *jsText = [NSString stringWithFormat:@"jsGetValueFromOc('%@')",@"哈哈"];
[self.webView stringByEvaluatingJavaScriptFromString:jsText];
方式二
通过使用JavaScriptCore
JSValue *callback = self.jsContext[@"jsGetValueFromOc"];
[callback callWithArguments:@[@"222"]];
或者
NSString *jsText = @"jsGetValueFromOc('222')";
[self.jsContext evaluateScript:jsText];
注意:stringByEvaluatingJavaScriptFromString是一个同步的方法,使用它执行JS方法时,如果JS 方法比较耗的时候,会造成界面卡顿。
官方推荐使用WKWebView(ios8)的evaluateJavaScript:completionHandler:代替这个方法。