js与原生通讯在iOS6.0及以前,只能通过
UIWebView的UIWebViewDelegate协议
| (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType |
方法来做拦截,并在这个方法中,根据url来调用Objective-C方法
一.javascript调用Objective-C
方法1 直接改变当前页面的url 这种方法在电脑浏览器中会直接跳转,在手机中正常
javascript代码:
|
functioncallOC(func,param){
varurl="myapp:"+"&func="+func;
for(variinparam)
{
url=url+"&"+i+"="+param[i];
//alert(i);
//alert(param[i]);
}
document.location=url;
//document.location="myapp:func¶m1=value1¶m2=value2...".
}
|
方法2 动态添加个iframe改变其地址 最后删除,这种方法不会使当前页面跳转 效果更佳
javascript代码:
| function callOC2(func,param){ var iframe = document.createElement("iframe"); var url= "myapp:" + "&func=" + func; for(var i in param) { url = url + "&" + i + "=" + param[i]; } iframe.src = url; iframe.style.display = 'none'; document.body.appendChild(iframe); iframe.parentNode.removeChild(iFrame); iframe = null; } |
|
使用方法
<inputtype="button"value="传个字典"onclick="callOC('testFunc',{'param1':76,'param2':155,'param3':76})"
/>
<inputtype="button"value="传个字典2"onclick="callOC2('testFunc',{'param1':76,'param2':155,'param3':76})"
/>
|
Objective-C代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; if ([requestString hasPrefix:@"myapp:"]) { NSLog(@"requestString:%@",requestString); //如果是自己定义的协议, 再截取协议中的方法和参数, 判断无误后在这里手动调用oc方法 NSMutableDictionary *param = [self queryStringToDictionary:requestString]; NSLog(@"get param:%@",[param description]); NSString *func = [param objectForKey:@"func"]; if([func isEqualToString:@"callFunc"]) { [self testFunc:[param objectForKey:@"first"] withParam2:[param objectForKey:@"second"] andParam3:[param objectForKey:@"third"] ]; } /* * 方法的返回值是BOOL值。 * 返回YES:表示让浏览器执行默认操作,比如某个a链接跳转 * 返回NO:表示不执行浏览器的默认操作,这里因为通过url协议来判断js执行native的操作,肯定不是浏览器默认操作,故返回NO * */ return NO; } return YES; } |
|
-(NSMutableDictionary*)queryStringToDictionary:(NSString*)string{
NSMutableArray*elements=(NSMutableArray*)[string
componentsSeparatedByString:@"&"];
NSMutableDictionary*retval=[NSMutableDictionary
dictionaryWithCapacity:[elementscount]];
for(NSString*einelements){
NSArray*pair=[e
componentsSeparatedByString:@"="];
[retval
setObject:[pair
objectAtIndex:1]?:@""
forKey:[pair
objectAtIndex:0]?@:"nokey"];
}
returnretval;
}
|
二.Objective-C调用javascript
| //插入js 并且执行传值 - (IBAction)insertJSTouched:(id)sender { NSString *insertString = [NSString stringWithFormat: @"var script = document.createElement('script');" "script.type = 'text/javascript';" "script.text = \"function jsFunc() { " "var a=document.getElementsByTagName('body')[0];" "alert('%@');" "}\";" "document.getElementsByTagName('head')[0].appendChild(script);", self.someString]; NSLog(@"insert string %@",insertString); [self.myWeb stringByEvaluatingJavaScriptFromString:insertString]; [self.myWeb stringByEvaluatingJavaScriptFromString:@"jsFunc();"]; } |
|
//提交form表单
-(IBAction)submitTouched:(id)sender{
[self.myWeb
stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit();
"];
}
|
| //修改标签属性 - (IBAction)fontTouched:(id)sender { NSString *tempString2 = [NSString stringWithFormat:@"document.getElementsByTagName('p')[0].style.fontSize='%@';",@"19px"]; [self.myWeb stringByEvaluatingJavaScriptFromString:tempString2]; } |
(PS)如果你想去掉webview弹出的alert 中的来自XXX网页
|
-(void)webViewDidFinishLoad:(UIWebView*)webView
{
//重定义web的alert方法,捕获webview弹出的原生alert 可以修改标题和内容等等
[webView
stringByEvaluatingJavaScriptFromString:@"window.alert
= function(message) { window.location = \"myapp:&func=alert&message=\" + message; }"];
}
|
| if([func isEqualToString:@"alert"]) { [self showMessage:@"来自网页的提示" message:[param objectForKey:@"message"]]; } |
|
(BOOL)webView:(UIWebView*)webViewshouldStartLoadWithRequest:(NSURLRequest*)requestnavigationType:(UIWebViewNavigationType)navigationType
|
方法来做拦截,并在这个方法中,根据url来调用Objective-C方法
但是iOS7之后, iOS 7 引入了 JavaScriptCore.framework库,它把 WebKit 的 JavaScript 引擎用 Objective-C 封装,让JavaScript与Objective-C之间的通信变的非常简单。首先导入JavaScriptCore.framework框架, 然后
JS端:
1
|
TXBB_IOS_SDK.callPay(charge, this .success, this .cancel);
|
OC端:
.h中引入头文件,并实现协议和对应的方法

.m中在webViewDidFinishLoad中给context赋值,并把self指针给TXBB_IOS_SDK,JS端即可经过TXBB_IOS_SDK.callPay调用起Native方法
1
2
3
4
5
6
7
8
9
10
11
12
|
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
self.context = [webView valueForKeyPath:@ "documentView.webView.mainFrame.javaScriptContext" ];
self.context[@ "TXBB_IOS_SDK" ] = self;
}
#pragma mark - JSExport Methods
- (void)callPay:(NSString *)charge success:(NSString *) success cancel:(NSString *)cancel {
...
[Pingpp createPayment:charge appURLScheme:@ "msc" withCompletion:completion];
}
|
Native -> Js
OC端调用JS代码则只需通过context调用evaluateScript方法即可,下列代码即会用JS显示Hello World,而在iOS7.0之前你可能通过[webView stringByEvaluatingJavaScriptFromString:@"document.title"]方法来获取WebView的title。
1
2
3
4
5
6
|
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
JSContext *context=[webView valueForKeyPath:@ "documentView.webView.mainFrame.javaScriptContext" ];
NSString *alertJs=@ "alert('Hello Word')" ;
[context evaluateScript:alertJs];
}
|
最后
JS和OC通信还有个非常著名的第三方库WebViewJavascriptBridge,如果你的项目需要支持iOS6之前的系统,你可以通过这个项目实现JS和OC的通信。
参考链接:
http://www.skyfox.org/javascript-ios-navive-message.html
http://www.cocoachina.com/ios/20150906/13320.html
|
(BOOL)webView:(UIWebView*)webViewshouldStartLoadWithRequest:(NSURLRequest*)requestnavigationType:(UIWebViewNavigationType)navigationType
|
方法来做拦截,并在这个方法中,根据url来调用Objective-C方法