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程序员和前端程序员协商好它们之间的关系,总体说来还是比较麻烦的。

猜你喜欢

转载自blog.csdn.net/jiuchabaikaishui/article/details/54378812