参考
总评:
oc 与js的交互,1.有原生的方式,oc 调js简单,js调oc 麻烦(协议拦截"实现的交互方式)。
2.iOS7之前,苹果没有出 JavaScriptCore 之前,业界普遍采用开源库WebViewJavascriptBridge和EasyJSWebView来解决的,原理都是基于拦截协议的封装,
3.iOS7之后,苹果针对JavaScript出了一个官方的库JavaScriptCore,是Objective-C封装了WebKit的JavaScript引擎,使我们可以脱离WebView执行JS代码。所以在iOS7之后想要实现交互,采用JavaScriptCore也是一种不错的选择,前提是你的项目不需要兼容到iOS7之前(觉得现在应该不那么强调要兼容到iOS7了吧)
4.iOS8发布的时候,苹果又推出了WKWebView,对之前的UIWebView进行了一次脱胎换骨的重构(将UIWebView和UIWebViewDelegate重构成了14个类和3个协议),功能也更加完善和强大,稳定性和性能也明显提高。
一,方法互调(首先声明的是无论如何互调,都需要两边配合的,有点像与后台的交互)
1.1 oc 调用js方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
示例:
if (sender.tag == 234) {
[self.webView stringByEvaluatingJavaScriptFromString:@"alertSendMsg('18870707070','周末爬山真是件愉快的事情')"];
}
//参数无限制
直接oc调用js的函数代码,也是强悍!
对应的js:
小黄
1.2 js调用oc 的方法(那就麻烦咯)
js那边不麻烦,也就加个链接
小黄
ps:"_"用作OC方法名中冒号的替换(这个应该是特殊字符的转义吧)
麻烦的是oc这边(其实就是对js传过来的url进行处理,分解出方法名和参数,通过OC执行选择器(selector)方法,来实现,不过这种方式最多只能传递参数的个数为2个,如果需要多个参数,可以从数据结构的组织方面入手)
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(@"%@",NSStringFromSelector(_cmd));
//OC调用JS是基于协议拦截实现的 下面是相关操作
NSString *absolutePath = request.URL.absoluteString;
NSString *scheme = @"rrcc://";
if ([absolutePath hasPrefix:scheme]) {
NSString *subPath = [absolutePath substringFromIndex:scheme.length];
if ([subPath containsString:@"?"]) {//1个或多个参数
if ([subPath containsString:@"&"]) {//多个参数
NSArray *components = [subPath componentsSeparatedByString:@"?"];
NSString *methodName = [components firstObject];
methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
//这段处理后的methodName结果是@"showSendNumber:msg:"(为了利用OC执行选择器(selector)方法,来实现)
SEL sel = NSSelectorFromString(methodName);
NSString *parameter = [components lastObject];
NSArray *params = [parameter componentsSeparatedByString:@"&"];
if (params.count == 2) {
if ([self respondsToSelector:sel]) {
//OC执行选择器(selector)方法关键是这一句了
[self performSelector:sel withObject:[params firstObject] withObject:[params lastObject]];
}
}
} else {//1个参数
NSArray *components = [subPath componentsSeparatedByString:@"?"];
NSString *methodName = [components firstObject];
methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
SEL sel = NSSelectorFromString(methodName);
NSString *parameter = [components lastObject];
if ([self respondsToSelector:sel]) {
[self performSelector:sel withObject:parameter];
}
}
} else {//没有参数
NSString *methodName = [subPath stringByReplacingOccurrencesOfString:@"_" withString:@":"];
SEL sel = NSSelectorFromString(methodName);
if ([self respondsToSelector:sel]) {
[self performSelector:sel];
}
}
}
return YES;
}
二,内容上的交互
就目前所知,oc 直接修改webview的内容比较方便,但是,js 想直接修改oc 的界面内容貌似不可以。(不知道是不是苹果方面出于安全方面的考虑,不给随随便便的一个网页这种权限?)
2.1 oc 修改webView的内容
这些操作,貌似都是在这个delegate里进行的
// 网页视图加载完毕会调用代理的这个方法
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
}
2.1.1 取
首先必须强调的是除非有且仅有唯一的标签,比如网页只有一个
那么就可以直接拿
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
//获取URL
NSString *curURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
而有多个
确没有标示,是拿不了的(不过这种情况少啊)2.1.2 改
//修改属性值
NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('good')[0].color='red';"];
2.1.3 删
NSString *str = @"document.getElementsByClassName('detail_btns2')[0].remove();";
[webView stringByEvaluatingJavaScriptFromString:str];
2.1.4
好像找不到“增”和“查”啊,擦~
最后
当然也有一些封装的库,不过还是建议用苹果提供的吧(JavaScriptCore)