UIWebView中Objective-C与JavaScript交互

转载 2016年05月30日 17:30:39

UIWebView中Objective-C与JavaScript交互

image

现在越来越多的项目为了支持公司业务的发展而选择使用HTML5做一些功能,那么这样就会涉及到HTML5与原生Objective-C的交互,今天就聊聊HMTL与原生之间的相互调用问题。

概述

原生与Web页面的交互可以分为Objective-C执行JavaScript代码和Web页面(或JavaScript)执行Objective-C代码,前者相对非常简单,后面可以通过JavaScriptCore、拦截协议等方式实现,下面我将主要对这二种方式进行叙述。

Objective-C执行JavaScript代码

打开UIWebView的头文件我们可以发现有一个方法叫stringByEvaluatingJavaScriptFromString:,它就是Objective-C执行JavaScript代码的通路,并且要注意它的返回值是NSString,这个方法在平时非常实用,列举几个例子:

// 获取当前页面的title
NSString *title = [webview stringByEvaluatingJavaScriptFromString:@"document.title"];

// 获取当前页面的可高度
float offsetHeight = [[webview stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];

// 获取需要分享的类内
NSString *sharedDictionary = [webview stringByEvaluatingJavaScriptFromString:@"getSharedContent"];

JavaScript执行Objective-C代码

JavaScript执行Objective-C代码之前我就说过有二种方式,现在我分别来说说这二种方式。

1. 利用JavaScriptCore来执行Objective-C代码

iOS7之后苹果推出了JavaScriptCore这个框架,从而让Web页面和本地原生应用交互起来非常方便,而且使用此框架可以做到Android那边和iOS相对统一,web前端写一套代码就可以适配客户端的两个平台,从而减少了Web前端的工作量。

Web前端

在三端交互中,web前端要强势一些,一切传值、方法命名都按web前端开发人员来定义,让另外两端去做适配。在这里以调用分享为例来详细讲解,测试网页代码取名为shared.html,其代码内容如下:

shared.html代码内容

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <title>js调用objective-c代码</title>
    <style type="text/css">
        #backButton { 
            display: inline-block;
            width:50px; height:30px;
        }
    </style>
</head>

<body>
    <button id="backButton">返回</button>
    <script type="text/javascript">

        var btn = document.getElementById('backButton');

        btn.addEventListener('click', function() {
           callBackObj.letsGoBack();
        });
    </script>
</body>
</html>
iOS

iOS这边根据前端定义的方法名来写代码,但是有些时候web前端会让我们定义,但是我们定义好之后他又要修改,这时候就会很烦啊。所以碰到三端交互的时候最好就是让web前端去定义方法名,iOS和Android根据web前端定义好的去写代码。JavaScriptCore中web页面调用原生应用的方法可以用Delegate或Block两种方法,此文以按Delegate讲解。

JavaScriptCore中类及协议:

JSContext:给JavaScript提供运行的上下文环境
JSValue:JavaScript和Objective-C数据和方法的桥梁
JSManagedValue:管理数据和方法的类
JSVirtualMachine:处理线程相关,使用较少
JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议

ViewController中的代码

- (void)webViewDidFinishLoad:(UIWebView *)webView {

    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    [context setExceptionHandler:^(JSContext *ctx, JSValue *value) {
    NSLog(@"error: %@", value);
}];

    context[@"callBackObj"] = self;
}

- (void) letsGoBack {
    [self.navigationController popViewControllerAnimated:YES];
}

ViewController中的代码解释

看到上面的代码我们可以看到设置了context中的callBackObj为self,通过这样的设置js在使用callBackObj.letsGoBack时其实等价于在viewController中使用[self letsGoBack]。

运行效果如图所示

image

拦截协议

首先我说解释一下什么是协议,协议是共同计议的规定,是大家一起遵循的准则。拦截协议这个非常适合各个平台,不需要引入什么框架,只需要大家相互之间遵守协议就可以了。那么在我们团队中协议是怎么定义的呢?scheme://model/aciton?{参数1}={数值1}&{参数2}={数值2}&…,比如在金蛋中分享的协议会是:jindanlicai://active/shared?callback=result(‘%s’,‘%s’)&function=getContent()。其中,function的值是可以获取分享内容的JavaScript函数名称,callback的值是分享结束之后调用的方法来告知HTML5是否分享成功与失败状态。

web前端

home.html中的代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div>
            <input type="button" value="分享" onclick="share()">
        </div>

        <script>
        function share() {
            window.location.href = 'jindanlicai://active/shared?callback=result('%s','%s')&function=getContent()';
        }
        </script>
    </body>
</html>

home.html中的代码解释

通过点击分享按钮将会调用JavaStript中的share(),window.location.href这里是改变主窗口的指向从而马上发出一个链接为‘jindanlicai://active/shared?callback=result(‘%s’,‘%s’)&function=getContent()’请求,而在iOS方法中我们要拦截这个请求,根据URL请求内容去判断Web页面想要原生做的事情,从而实现web页面和本地应用之间的交互。

iOS

iOS对应的代码

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    if ([[request.URL scheme] isEqualToString:@"jindanlicai"]) {
        [JDOpenURL handlerURL:request.URL context:self];
        return NO;
    }
    return YES;
}

iOS对应的代码的解释

在webView的代理方法中去拦截URL的scheme为自定义jindanlicai协议,调用原生提前约定好的方法,并且返回值为NO来阻止此链接的跳转。

总结

随着手机硬件的配置越来越强大和HTML5的兴起,一个App完全可以由web页面来写。现在在我们公司已经有很多的App已经完全是这么干了,iOS和Android只是给这个App套一个壳并通过一些协议去实现一些本地逻辑。协议是一个非常不错的方法,在这我推荐使用协议去做这样的事,当前提前是你要非常理解协议。如果有人喜欢协议,WebViewJavaScriptBridge是一个不错的第三库。

相关文章推荐

UIWebView 与 JS 交互(1):Objective-C 调用 Javascript

作为一名普通的 iOS 开发者,我们在项目中也会或多或少的用到一些 JS 代码,如何实现 JS 和 OC 之间的交互常常是我们会面临的一个问题。最近一段时间,笔者最近由于工作需要,研究了很多 iOS ...

iOS UIWebView中Objective-C与Javascript的深层交互(三)

上篇文章中讲述了如何通过代码直接用JavaScript调用Objective-C方法,本文通过另一种思路实现,即通过稍微复杂的一种方法,即通过一个对象来调用方法,该方法通过实现一个协议来操作,即JSE...

iOS UIWebView中javascript与Objective-C交互、获取摄像头

iOS UIWebView中javascript与Objective-C交互、获取摄像头 UIWebView是iOS开发中常用的一个视图控件,多数情况下,它被用来显示HTML格式的内容。 ...

使用UIWebView时objective-c与javascript互相调用

原址:http://www.cnblogs.com/zhwl/archive/2013/04/19/3030244.html 在写 JavaScript 的时候,可以使用一个叫做 w...

[iOS] 使用UIWebView时objective-c与javascript互相调用 1

原文转自:http://zonble.net/archives/2010_09/1385.php 在写 JavaScript 的时候,可以使用一个叫做 window 的对象,像是我们想要从现在的网页...
  • mkhgg
  • mkhgg
  • 2011年12月26日 23:24
  • 5820

使用UIWebView时objective-c与javascript互相调用 1

原文转自:http://zonble.net/archives/2010_09/1385.php 在写 JavaScript 的时候,可以使用一个叫做 window 的对象,像是我们想要从现在的网页...

JavaScript和Objective-C的交互

JavaScript和Objective-C的交互在iOS开发中,因为H5页面的一些先天优势,原生界面里面掺杂着H5页面是一种很常见的方案。公司应用最近因为业务需要一下子接入了大量H5界面,另外还要求...

Objective-C与JavaScript的交互

UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS...

Objective-c与javascript交互

在写 JavaScript 的时候,可以使用一个叫做 window 的对象,像是我们想要从现在的网页跳到另外一个网页的时候,就会去修改 window.location.href 的位置;在我们的 Ob...

WebView中JavaScript与Objective-C的交互

MacOS开发中WebView已经实现了浏览器的基本功能,使用十分方便,要在WebView中实现JS调用Obj-c的代码个人觉的需要一下几个基本步骤: 1. 要使用WebView需要添加WebKit...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UIWebView中Objective-C与JavaScript交互
举报原因:
原因补充:

(最多只允许输入30个字)