iOS UIWebView与JavaScript交互
前言
在iOS开发中,我们经常需要加载网页,在很多时候难免需要和网页进行交互,而这种交互实质上就是UIWebView与JavaScript之间的交互,在iOS7苹果增加了JavaScriptCore来实现这种交互,那么在iOS之前是怎样来的呢?在这篇文章中就围绕这些问题来讲述。
iOS执行JavaScript代码
Simulator Screen Shot 2016年11月13日 下午10.40.07.png客户端向JS传递数据,通过插入JS方法来实现,通过UIWebView的这个方法- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script可以执行JavaScript代码:
//定义一个js函数,函数的功能是弹出一个内容为“哈哈”的警告框。
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"function showMessageAction(){alert('哈哈');}"]];
那么JavaScript就直接调用window.showMessageAction()就可以调用这个方法啦。通过这样的方式,我们不但可以定义JavaScritp函数、执行JavaScritp函数,也可以传递数据(直接返回就行啦)。由于android的addJavascriptInterface()方法中有两个参数,若第二个参数传入字符串,比如test,则JS的调用需要更改为 window.test.showMessageAction()。为了使IOS与android的调用保持一致,则需要对js进行修改,具体修改形式:
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"var test = {}; (function initialize() { test.showMessageAction = function showMessageAction(){ alert('哈哈'); }; })()"]];
这样在IOS环境下JS也可以通过调用 window.test.showMessageAction()来获取用户名了。
JavaScript调用oc代码
Simulator Screen Shot 2016年11月13日 下午10.41.54.png在JavaScriptCore出现之前,似乎没有专门的API来做这件事,但是还是可以通过一些办法来达到此目的。这里讨论的实现思想是通过对UIWebView的delegate方法
-(BOOL)webView: shouldStartLoadWithRequest: navigationType:
进行处理来实现的。劫持UIWebview所加载的url来判断是否是需要处理的条件即可。
- 首先我们定义一种URL格式:
协议名:函数名?参数1&参数2&…… - 接着在JavaScript中调用一个如下方法:
document.location = "协议名:函数名?参数1&参数2&……";
- 最后在UIWebView监听加载的URL,并就此作出相应的操作。
例如:
- 先在html中写一个如下的按钮:
<button type="button" name="btn2" id="btn2" value="提示" onclick="javaScript:button2Action();">js调用OC弹出框</button>
- 接着写一个如下JavaScript函数:
function button2Action()
{
document.location = "test:showAlertView?提示&OC弹出框&确定";
}
- 最后对UIWebView的delegate方法
-(BOOL)webView: shouldStartLoadWithRequest: navigationType:
进行处理:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
// 处理事件
NSString *requestString = [[[request URL] absoluteString] stringByRemovingPercentEncoding];
NSLog(@"%@", requestString);
NSArray *requestsArr = [requestString componentsSeparatedByString:@":"];
if (requestsArr != nil && [requestsArr count] > 0) {
NSString *pocotol = [requestsArr objectAtIndex:0];
if ([pocotol isEqualToString:@"test"]) {
NSString *commandStr = [requestsArr objectAtIndex:1];
NSArray *commandArr = [commandStr componentsSeparatedByString:@"?"];
if (commandArr != nil && [commandArr count] > 0) {
NSString *command = [commandArr objectAtIndex:0];
NSString *parameterStr = [commandArr objectAtIndex:1];
NSArray *parameterArray = [parameterStr componentsSeparatedByString:@"&"];
if ([command isEqualToString:@"showAlertView"]) {
NSString *title;
NSString *message;
NSArray *otherButtonTitles;
if (parameterArray && parameterArray.count > 0) {
title = parameterArray[0];
}
if (parameterArray && parameterArray.count > 1) {
message = parameterArray[1];
}
if (parameterArray && parameterArray.count > 2) {
otherButtonTitles = [parameterArray subarrayWithRange:NSMakeRange(2, parameterArray.count - 2)];
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *alertAction;
for (NSString *buttonTitle in otherButtonTitles) {
alertAction = [UIAlertAction actionWithTitle:buttonTitle style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:alertAction];
}
[self presentViewController:alertController animated:YES completion:nil];
}
}
return NO;
}
}
return YES;
}
通过这样的方式来做交互,需要iOS程序员和前端程序员协商好它们之间的关系,总体说来还是比较麻烦的。