iOS开发-基于原生JS与OC方法互相调用并传值(附HTML代码)

最近项目里面有有个商品活动界面,要与web端传值,将用户在网页点击的商品id 传给客户端,也就是js交互,其实再说明白一点就是方法的互相调用而已。

本文叙述下如何进行原生的JavaScript交互

本文包括JS调用OC方法并传值,OC调用JS方法并传值

本来想把html放进服务器里面,然后访问,但是觉得如果html在本地加载更有助于理解,特把html放进项目里

HTML代码

<span style="font-family: Arial;"></span><pre class="hljs xml" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="xml"><span class="hljs-doctype" style="color: rgb(102, 0, 102);"><!DOCTYPE html></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">html</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">head</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">meta</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">charset</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"UTF-8"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">head</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">body</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">div</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">style</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"margin-top: 20px"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">h2</span>></span>JS与OC交互<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">h2</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">input</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">type</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"button"</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">value</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"唤起本地方法(call)"</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">onclick</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"tianbai.call()"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">div</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">div</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">input</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">type</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"button"</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">value</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"唤起getCall:(NSString *)callString传值"</span> <span class="hljs-attribute" style="color: rgb(102, 0, 102);">onclick</span>=<span class="hljs-value" style="color: rgb(0, 136, 0);">"call()"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">div</span>></span>

<span class="hljs-tag" style="color: rgb(0, 102, 102);"><<span class="hljs-title" style="color: rgb(0, 0, 136);">script</span>></span></code>
<code class="xml"><span class="hljs-tag" style="color: rgb(0, 102, 102);"></span></code><pre class="hljs xml" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="xml"><span class="javascript"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">var</span> call = <span class="hljs-function"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">function</span>(<span class="hljs-params" style="color: rgb(102, 0, 102);"></span>)
</span>{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136);">var</span> callInfo = <span class="hljs-built_in" style="color: rgb(102, 0, 102);">JSON</span>.stringify({<span class="hljs-string" style="color: rgb(0, 136, 0);">"jianshu"</span>: <span class="hljs-string" style="color: rgb(0, 136, 0);">"http://www.jianshu.com/users/55c8fdc3c6e7/latest_articles"</span>});
        tianbai.getCall(callInfo);
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136);">var</span> Callback = <span class="hljs-function"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">function</span>(<span class="hljs-params" style="color: rgb(102, 0, 102);">str</span>)
</span>{
    alert(str);
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136);">var</span> alerCallback = <span class="hljs-function"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">function</span>(<span class="hljs-params" style="color: rgb(102, 0, 102);"></span>)
</span>{
    alert(<span class="hljs-string" style="color: rgb(0, 136, 0);">'成功'</span>);
}
</span><span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">script</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">body</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102);"></<span class="hljs-title" style="color: rgb(0, 0, 136);">html</span>></span></code>
 
 


上面html的代码:建立了两个button

第一个button绑定了 tianbai.call() 方法,这里 tianbai 是一个对象,这个对象的作用下面OC代码中会说明,tianbai.call() 代表 tianbai 对象调用 call() 方法

第二个button绑定了 call() 的方法,调用的是下面JavaScript中的 call() 方法,在 JavaScript 的 call() 里面,定义一个 callInfo 参数,方法中 tianbai.getCall(callInfo) 代表 tianbai 对象调用 getCall 方法并传参数 callInfo ,下面两个方法是OC调用JavaScript方法,其中Callback传回str,alerCallback为OC仅调用JavaScript方法!


OC代码


demo采用原生的JavaScriptCore类

引入三个名词:

  1. JSContext:给JavaScript提供运行的上下文环境
  2. JSValue:JavaScript和Objective-C数据和方法的桥梁
  3. JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议

ViewController.h中的代码(代码过长,方法说明都在注释里)

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68);">#import <span class="hljs-title"><UIKit/UIKit.h></span></span>
<span class="hljs-comment" style="color: rgb(136, 0, 0);">//导入头文件</span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68);">#import <span class="hljs-title"><JavaScriptCore/JavaScriptCore.h></span></span>

<span class="hljs-class"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">@protocol</span> <span class="hljs-title" style="color: rgb(102, 0, 102);">JSObjcDelegate</span> <<span class="hljs-title" style="color: rgb(102, 0, 102);">JSExport</span>></span>
<span class="hljs-comment" style="color: rgb(136, 0, 0);">//tianbai对象调用的JavaScript方法,必须声明!!!</span>
- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)call;
- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)getCall:(<span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSString</span> *)callString;

<span class="hljs-keyword" style="color: rgb(0, 0, 136);">@end</span>
<span class="hljs-class"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">@interface</span> <span class="hljs-title" style="color: rgb(102, 0, 102);">ViewController</span> : <span class="hljs-title" style="color: rgb(102, 0, 102);">UIViewController</span><<span class="hljs-title" style="color: rgb(102, 0, 102);">UIWebViewDelegate</span>,<span class="hljs-title" style="color: rgb(102, 0, 102);">JSObjcDelegate</span>></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136);">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">nonatomic</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136);">strong</span>) JSContext *jsContext;
<span class="hljs-keyword" style="color: rgb(0, 0, 136);">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">strong</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136);">nonatomic</span>)  <span class="hljs-built_in" style="color: rgb(102, 0, 102);">UIWebView</span> *webView;

<span class="hljs-keyword" style="color: rgb(0, 0, 136);">@end</span></code>

 

ViewController.m中的代码(代码过长,方法说明都在注释里)

JavaScriptCore中web页面调用原生应用的方法可以用Delegate或Block两种方法,此文以按Delegate讲解。

设置webView

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec"><span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.webView</span> = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102);">UIWebView</span> alloc]initWithFrame:<span class="hljs-built_in" style="color: rgb(102, 0, 102);">CGRectMake</span>(<span class="hljs-number" style="color: rgb(0, 102, 102);">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102);">20</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102);">UIScreen</span> mainScreen]<span class="hljs-variable" style="color: rgb(102, 0, 102);">.bounds</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.size</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.width</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102);">UIScreen</span> mainScreen]<span class="hljs-variable" style="color: rgb(102, 0, 102);">.bounds</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.size</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.height</span>)];
    <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.webView</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.delegate</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span>;
    <span class="hljs-comment" style="color: rgb(136, 0, 0);">//从本地加载html文件</span>
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSString</span>* path = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSBundle</span> mainBundle] pathForResource:<span class="hljs-string" style="color: rgb(0, 136, 0);">@"index"</span> ofType:<span class="hljs-string" style="color: rgb(0, 136, 0);">@"html"</span>];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSURL</span>* url = [<span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSURL</span> fileURLWithPath:path];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSURLRequest</span>* request = [<span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSURLRequest</span> requestWithURL:url] ;
    [<span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.webView</span> loadRequest:request];

    [<span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.view</span> addSubview:<span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.webView</span>];</code>

 

JavaScript的tianbai是一个对象,充当原生应用和web页面之间的一个桥梁。用来调用方法

webview加载完成调用代理

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)webViewDidFinishLoad:(<span class="hljs-built_in" style="color: rgb(102, 0, 102);">UIWebView</span> *)webView {

      <span class="hljs-comment" style="color: rgb(136, 0, 0);">// 设置javaScriptContext上下文</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span> = [webView valueForKeyPath:<span class="hljs-string" style="color: rgb(0, 136, 0);">@"documentView.webView.mainFrame.javaScriptContext"</span>];
    <span class="hljs-comment" style="color: rgb(136, 0, 0);">//将tianbai对象指向自身</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span>[<span class="hljs-string" style="color: rgb(0, 136, 0);">@"tianbai"</span>] = <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.exceptionHandler</span> = ^(JSContext *context, JSValue *exceptionValue) {
        context<span class="hljs-variable" style="color: rgb(102, 0, 102);">.exception</span> = exceptionValue;
        <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSLog</span>(<span class="hljs-string" style="color: rgb(0, 136, 0);">@"异常信息:%@"</span>, exceptionValue);
    };
}</code>
 

将对象指向自身后,如果调用 tianbai.call() 会响应下面的方法,OC方法中调用js中的Callback方法,并传值

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)call{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSLog</span>(<span class="hljs-string" style="color: rgb(0, 136, 0);">@"call"</span>);
    <span class="hljs-comment" style="color: rgb(136, 0, 0);">// 之后在回调JavaScript的方法Callback把内容传出去</span>
    JSValue *Callback = <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span>[<span class="hljs-string" style="color: rgb(0, 136, 0);">@"Callback"</span>];
    <span class="hljs-comment" style="color: rgb(136, 0, 0);">//传值给web端</span>
    [Callback callWithArguments:@[<span class="hljs-string" style="color: rgb(0, 136, 0);">@"唤起本地OC回调完成"</span>]];
}</code>
 

将对象指向自身后,如果调用 tianbai.getCall(callInfo) 会响应下面的方法,OC方法中仅调用JavaScript中的alerCallback方法

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)getCall:(<span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSString</span> *)callString{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSLog</span>(<span class="hljs-string" style="color: rgb(0, 136, 0);">@"Get:%@"</span>, callString);
    <span class="hljs-comment" style="color: rgb(136, 0, 0);">// 成功回调JavaScript的方法Callback</span>
    JSValue *Callback = <span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span>[<span class="hljs-string" style="color: rgb(0, 136, 0);">@"alerCallback"</span>];
    [Callback callWithArguments:<span class="hljs-literal" style="color: rgb(0, 102, 102);">nil</span>];
}</code>
 

将对象指向自身后,还可以向html注入js

<pre class="hljs objectivec" name="code" style="white-space: pre-wrap; word-wrap: break-word; padding: 0.5em; background-color: rgb(255, 255, 255); font-size: 14px;"><code class="objectivec">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136);">void</span>)alert{

    <span class="hljs-comment" style="color: rgb(136, 0, 0);">// 直接添加提示框</span>
    <span class="hljs-built_in" style="color: rgb(102, 0, 102);">NSString</span> *str = <span class="hljs-string" style="color: rgb(0, 136, 0);">@"alert('OC添加JS提示成功')"</span>;
    [<span class="hljs-keyword" style="color: rgb(0, 0, 136);">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102);">.jsContext</span> evaluateScript:str];

}</code>

 

Demo地址:点击下载



文/TianBai(简书作者)
原文链接:http://www.jianshu.com/p/fd378c6d70c0
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值