🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# JS与OC交互协议 ### iOS与H5交互说明 iOS与H5交互,采用是JavaScriptCore方式。原理是iOS端在WebView加载完一个URL链接的时候,手动向H5页面绑定一个`JSContext`对象。利用这个JSContext对象,可以实现OC与JS间的双向交互。**注意:JSContext对象是在iOS的`webViewDidFinishLoad:`回调里完成绑定的,在完成绑定前无法使用JS与OC的任何交互。** ### JS调用OC接口 ##### JS开始调用OC接口前,有几个前提条件: + js的window.isReady方法已经触发过了,JS才能调用OC提供的方法。原因是iOS会在JSContext对象绑定成功后,才会向js端调用isReady方法,所以js只有等isReady触发了,才能通过JSContext调用OC方法。 + iOS在绑定JSContext对象的时候,要约定好一个字段,然后OC会将原生方法注册到网页window对象的这个字段上。比如`window.xhxapp`。 + js端如果要异步接收原生方法的返回结果,需要在全局作用域内定义好回调方法 ​ ##### JS示例代码: js调用OC原生方法,同步获取用户基本信息 ````js // 约定好获取用户信息接口注册到window的xhxapp属性上 // getUserInfo方法是一个同步方法,可以js端可以直接获取到返回值 // 返回的对象可以是json字符串 var info = window.xhxapp.getUserInfo() ```` js调用OC原生方法,拍照上传作业图片,并异步获取上传结果 ```js // 假设约定好作业相关的OC接口都注册到window的homework属性上 window.homework.uploadHomeworkPicture(questionID) // 在全局作用域内定义好回调方法,用于接收返回值 // 原生方法会在上传完作业图片的时候,间接调用该回调方法 function homeworkPictureDidUploaded(questionID, picUrl) { // do something... } ``` ##### JS里调用通用原生接口: ```swift /** 跳转到课程详情 @param productId 商品ID(string类型) */ xhxapp.gotoCourseDetail(productId); /** 关闭当前页面 */ xhxapp.finish(); /** 获取用户信息,已json字符串形式返回。主要字段如下: memberId: 用户id token: 用户登录唯一标识 memberType: 用户类型 */ xhxapp.getUserInfo(); /** toast提示 @param msg 提示语(string类型) */ xhxapp.toast(msg); /** 显示对话框 @param title 标题(string字符串) @param msg 消息(string字符串) @param actions 点击事件(一个json数组字符串),每个数组元素字段如下: title: 事件标题(string字符串,比如“取消”) callback: 事件的js回调方法(string字符串) 示例: var actions = "[{'title': '取消', 'callback': 'cancelPay'}, {'title': '确定', 'callback': 'confirmPay'}]"; xhxapp.confirm("温馨提示", "是否支付订单?", actions); */ xhxapp.confirm(title, msg, actions); ``` ### OC调用JS接口 ##### OC在调用JS方法时的注意事项: + js方法应该申明到全局作用域内,否则OC获取不到该方法 + 如果在`webViewDidFinishLoad:`直接用过JSContext调用js方法,可能会出现调用无效的请求。为了避免此类问题,推荐以`setTimeout`方式调用js方法 ##### 示例代码: OC在webViewDidFinishLoad:中调用js的`isReady`方法 ```objective-c // setTimeout是JS的自带方法 // 这里使用setTimeout的目的是为了将isReady方法放到js调用队列的最后 JSValue *isReadyFunc = self.jsContext[@"isReady"]; if (isReadyFunc) { [self.jsContext[@"setTimeout"] callWithArguments:@[isReadyFunc, @100]]; } ``` OC在JS发起的原生方法中调用js的setUserInfo方法 ```objective-c // 注意,JavaScriptCore支持NSDictionary、NSArray类型作参数传给js方法 NSDictionary *userInfo = ...; [self.jsContext[@"setUserInfo"] callWithArguments:@[userInfo]]; ``` ##### JS提供给原生调用的通用接口定义: ```swift /** iOS原生初始化完成后调用本方法,告诉js已经准备好了 */ function isReady(); /** * return boolean 类型返回值: true h5已经处理了返回,native不处理; false h5没有处理返回,native直接返回上级原生页面 */ function gobackIfNeeded(); ``` ### APP唤醒 定义scheme: com.mistong.kklonline ### UserAgent WebView的默认UserAgent为:"xxxx XHX/1.3.0", 其中xxxx为系统默认UserAgent。''/''后为app版本号