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

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

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

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

HTML代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="margin-top: 20px">
<h2>JS与OC交互</h2>
<input type="button" value="唤起本地方法(call)" onclick="tianbai.call()">
</div>
<div>
<input type="button" value="唤起getCall:(NSString *)callString传值" onclick="call()">
</div> <script> var call = function()
{
var callInfo = JSON.stringify({"jianshu": "http://www.jianshu.com/users/55c8fdc3c6e7/latest_articles"});
tianbai.getCall(callInfo);
} var Callback = function(str)
{
alert(str);
}
var alerCallback = function()
{
alert('成功');
}
</script>
</body>
</html>

上面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中的代码(代码过长,方法说明都在注释里)

#import <UIKit/UIKit.h>
//导入头文件
#import <JavaScriptCore/JavaScriptCore.h> @protocol JSObjcDelegate <JSExport>
//tianbai对象调用的JavaScript方法,必须声明!!!
- (void)call;
- (void)getCall:(NSString *)callString; @end
@interface ViewController : UIViewController<UIWebViewDelegate,JSObjcDelegate>
@property (nonatomic, strong) JSContext *jsContext;
@property (strong, nonatomic) UIWebView *webView; @end

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

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

设置webView

self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
self.webView.delegate = self;
//从本地加载html文件
NSString* path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL* url = [NSURL fileURLWithPath:path];
NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
[self.webView loadRequest:request]; [self.view addSubview:self.webView];

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

webview加载完成调用代理

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

      // 设置javaScriptContext上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//将tianbai对象指向自身
self.jsContext[@"tianbai"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
}

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

- (void)call{
NSLog(@"call");
// 之后在回调JavaScript的方法Callback把内容传出去
JSValue *Callback = self.jsContext[@"Callback"];
//传值给web端
[Callback callWithArguments:@[@"唤起本地OC回调完成"]];
}

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

- (void)getCall:(NSString *)callString{
NSLog(@"Get:%@", callString);
// 成功回调JavaScript的方法Callback
JSValue *Callback = self.jsContext[@"alerCallback"];
[Callback callWithArguments:nil];
}

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

- (void)alert{

    // 直接添加提示框
NSString *str = @"alert('OC添加JS提示成功')";
[self.jsContext evaluateScript:str]; }

JS调用OC方法并传值,OC调用JS方法并传值////////////////////////zz的更多相关文章

  1. 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用

    1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...

  2. js中子页面父页面方法和变量相互调用

    (1)子页面调用父页面的方法或者变量: window.parent.方法()或者变量名window.parent相当于定位到父页面 之后的操作和在父页面中写代码一样写 window.parent.aa ...

  3. easyUi弹出window窗口传值与调用父页面的方法,子页面给父页面赋值

    <!-- 父页面 --> <!DOCTYPE html PUBLIC "-/W3C/DTD HTML 4.01 Transitional/EN" "ht ...

  4. (转)Silverlight调用的JS方法返回对象数组的处理方法

    最近在做Silverlight应用,需要用Silverlight调用页面中Javascript方法.这 个JS方法返回一个对象数组给Silverlight.对于这个对象数组怎么在Silverlight ...

  5. 「Vue」父子组件之间的传值及调用方法

    a.父组件向子组件传值data(){},props数据区别data中的数据可读可写,是自己的数据props是个数组,中的数据是父组件传递过来的,只读不能写<login :dmsg='msg'&g ...

  6. jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行?

    jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行? 因为在解析时最新解析的就是JA ...

  7. JS高级. 06 缓存、分析解决递归斐波那契数列、jQuery缓存、沙箱、函数的四种调用方式、call和apply修改函数调用方法

    缓存 cache 作用就是将一些常用的数据存储起来 提升性能 cdn //-----------------分析解决递归斐波那契数列<script> //定义一个缓存数组,存储已经计算出来 ...

  8. vue.js组件之间通讯--父组件调用子组件的一些方法,子组件暴露一些方法,让父组件调用

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. Vue父子组件相互传值及调用方法的方案

    Vue父子组件相互传值及调用方法的方案 一.调用方法: 1.父组件调用子组件方法: 2.子组件调用父组件方法: 参考:https://www.cnblogs.com/jin-zhe/p/9523782 ...

  10. JS设计模式——6.方法的链式调用

    什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 分解链式调用 链式调用其实是两个部分: 1.操作对象(也就是被操作的DOM元素 ...

随机推荐

  1. Android自动化测试 - Robotium之re-sign.jar重签名后安装失败提示Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]解决方案

    问题:在用re-sign.jar重签名apk文件后,显示重签名成功,但在实际安装过程中确提示:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES] 原因:网上查 ...

  2. Only Link: What's the difference between dynamic dispatch and dynamic binding

    http://stackoverflow.com/questions/20187587/what-is-the-difference-between-dynamic-dispatch-and-late ...

  3. 纯CSS完成tab实现5种不同切换对应内容效果

    很常用的一款特效纯CSS完成tab实现5种不同切换对应内容效果 实例预览 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...

  4. Leetcode Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  5. web Worker使js实现‘多线程’?

    大家都知道js是单线程的,在上一段js执行结束之前,后面的js绝对不会执行,那么为什么标题说js实现‘多线程’,虽然说加了引号,可是标题也不能乱写不是,可恶的标题党? 姑且抛开标题不说,先说我们经常会 ...

  6. ZooKeeper个人笔记之节点的监听

    create public String create(String path, byte[] data, List<ACL> acl, CreateMode createMode) th ...

  7. SQLite部署-无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块

    近期刚使用SQLite,主要引用的是System.Data.SQLite.dll这个dll,在部署到测试环境时报无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块. (异常来 ...

  8. Javascript的shift()和push(),unshift()和pop()方法简介

    栈方法: Javascript为数组专门提供了push()和pop()方法,以便实现类似栈的行为.来看下面的例子: var colors=new Array();       //创建一个数组 var ...

  9. mmysql-最大链接数和最大并发数的区别

    关于连接数和并发数的设置(针对Innodb引擎) 对于机器本身来说,进程数是说机器正在运行的进程数量,调出任务管理器就可以看到.连接数是指进程接收和发送数据的连接ip的数量.并发数是指进程同时发送数据 ...

  10. 获取打开指定Action的所有应用包名

    获取打开指定功能的所有应用:发消息,分享等等. 如打开网页,下面代码即可查看所有的浏览器 //查找所有浏览器 private void queryPackage() { PackageManager ...