您的位置:首页 > 移动开发 > IOS开发

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

2016-10-20 18:18 676 查看
最近项目里面有有个商品活动界面,要与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类引入三个名词:JSContext:给JavaScript提供运行的上下文环境
JSValue:JavaScript和Objective-C数据和方法的桥梁
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著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: