uiwebview与objective-c
利用oc调用js很简单, 系统直接提供了方法stringByEvaluatingJavaScriptFromString
[webView stringByEvaluatingJavaScriptFromString:@"document.location.href"]; [webview stringByEvaluatingJavaScriptFromString:@"JsMethod()"];
而反过来貌似不可以, oc没有提供直接的方法, 不过利用webview的一些小技巧达到目的!
webview提供了以下代理方法:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; - (void)webViewDidStartLoad:(UIWebView *)webView; - (void)webViewDidFinishLoad:(UIWebView *)webView; - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
方法很简单, 顾名思义! 将要开始请求/已经开始加载/完成加载/加载错误
利用shouldStartLoadWithRequest可以捕获到uiwebview的一切请求! 如果我们在js里面发送一个特定的请求, 里面包含将要调用的oc函数和请求参数, 这样我们利用这个代理方法捕捉到后加以匹配后手动调用不就可以达到目的了??? 是的, 这样完全行得通
举个例子, js里面可以这么写:
function sendCommand(cmd,param){ var url="protocol://"+cmd+":"+param; document.location = url; }
protocol是自己定义的一个协议, 只要不和http, https等国际通用协议头冲突都可以, 名字随便取;
cmd是要调用的oc的方法;
param是调用的参数
然后利用document.location来达到目的! 上面的"protocol://"+cmd+":"+param是自定义的一种请求格式, 这个格式你也可以变, 比如可以像下面这样
document.location="MyCustomProtocolName:functionName?param1=value1¶m2=value2...".
js里面怎么定义都可以, 怎么方便怎么来! 不过在shouldStartLoadWithRequest方法里面捕获到了这次请求后, 你要对应的解析, 判断是不是自己特定的请求!
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString* rurl=[[request URL] absoluteString]; if ([rurl hasPrefix:@"protocol://"]) { //如果是自己定义的协议, 再截取协议中的方法和参数, 判断无误后在这里手动调用oc方法 } return true; }
备注: stringByEvaluatingJavaScriptFromString这个方法有个地方需要注意, 算不上bug, 但确实有问题, 需要注意!
如果stringByEvaluatingJavaScriptFromString执行的是带参数的js函数, 这个参数里面如果带有(\r \n ')等等, js那边收不到这个值, 这些带\的需要转义, 如下这么写js才能收到完整的消息
message = [message stringByReplacingOccurrencesOfString:@"\n" withString:@"\\\\n"]; NSString *jsMethod = [NSString stringWithFormat:@"JsMethod(\"%@\")", message];
还有一个地方, 这2种写法看似一样, 实质不同, 如果是采用'引号, 如果message带有', 消息则传不过去! 所以最好采用"
NSString *jsMethod = [NSString stringWithFormat:@"JsMethod(\"%@\")", message]; NSString *jsMethod = [NSString stringWithFormat:@"JsMethod('%@')", message];
另外也有开源的js与webview通信的例子供用, 里面也有我上面提到的问题, 需要自己修改!
https://github.com/marcuswestin/WebViewJavascriptBridge