您好,欢迎来到时间财富网
全部需求分类
当前位置:首页 > 移动应用 > avascript直接开发原生APP,JS-OC通信实际操作方法
avascript直接开发原生APP,JS-OC通信实际操作方法
2015-11-16 02:39:59   作者:风雨考验   人气:2349次  评论(0)
所属标签: 移动应用开发 

React Native是facebook刚开源的框架,可以用javascript直接开发原生APP,先不说这个框架后续是否能得到大众认可,单从源码来说,这个框架源码里有非常多的设计思想和实现方式值得学习,小编先来看看它最基础的JavaScript-ObjectC通信机制(以下简称JS/OC)。

 

概览 

React Native用iOS自带的JavaScriptCore作为JS的解析引擎,但并没有用到JavaScriptCore提供的一些可以让JS与OC互调的特性,而是自己实现了一套机制,这套机制可以通用于所有JS引擎上,在没有JavaScriptCore的情况下也可以用webview代替,实际上项目里就已经有了用webview作为解析引擎的实现,应该是用于兼容iOS7以下没有JavascriptCore的版本。 


普通的JS-OC通信实际上很简单,OC向JS传信息有现成的接口,像webview提供的-stringByEvaluatingJavaScriptFromString方法可以直接在当前context上执行一段JS脚本,并且可以获取执行后的返回值,这个返回值就相当于JS向OC传递信息。React Native也是以此为基础,通过各种手段,实现了在OC定义一个模块方法,JS可以直接调用这个模块方法并还可以无缝衔接回调。 


举个例子,OC定义了一个模块RCTSQLManager,里面有个方法-query:successCallback:,JS可以直接调用RCTSQLManager.query并通过回调获取执行结果: 
Js代码 
  1. //OC:  
  2. @implement RCTSQLManager  
  3. - (void)query:(NSString *)queryData successCallback:(RCTResponseSenderBlOCk)responseSender  
  4. {  
  5.      RCT_EXPORT();  
  6.      NSString *ret = @"ret"  
  7.      responseSender(ret);  
  8. }  
  9. @end  

Js代码 
  1. //JS:  
  2. RCTSQLManager.query("SELECT * FROM table"function(result) {  
  3.      //result == "ret";  
  4. });  

接下来看看它是怎样实现的。 
模块配置表 
首先OC要告诉JS它有什么模块,模块里有什么方法,JS才知道有这些方法后才有可能去调用这些方法。这里的实现是OC生成一份模块配置表传给JS,配置表里包括了所有模块和模块里方法的信息。例: 
Js代码 
  1. {  
  2.     "remoteModuleConfig": {  
  3.         "RCTSQLManager": {  
  4.             "methods": {  
  5.                 "query": {  
  6.                     "type""remote",  
  7.                     "methodID": 0  
  8.                 }  
  9.             },  
  10.             "moduleID": 4  
  11.         },  
  12.         ...  
  13.      },  
  14. }  

OC端和JS端分别各有一个bridge,两个bridge都保存了同样一份模块配置表,JS调用OC模块方法时,通过bridge里的配置表把模块方法转为模块ID和方法ID传给OC,OC通过bridge的模块配置表找到对应的方法执行之,以上述代码为例,流程大概是这样(先不考虑callback): 

 

在了解这个调用流程之前,我们先来看看OC的模块配置表式怎么来的。我们在新建一个OC模块时,JS和OC都不需要为新的模块手动去某个地方添加一些配置,模块配置表是自动生成的,只要项目里有一个模块,就会把这个模块加到配置表上,那这个模块配置表是怎样自动生成的呢?分两个步骤: 
1.取所有模块类 
每个模块类都实现了RCTBridgeModule接口,可以通过runtime接口objc_getClassList或objc_copyClassList取出项目里所有类,然后逐个判断是否实现了RCTBridgeModule接口,就可以找到所有模块类,实现在RCTBridgeModuleClassesByModuleID()方法里。 
2.取模块里暴露给JS的方法 
一个模块里可以有很多方法,一些是可以暴露给JS直接调用的,一些是私有的不想暴露给JS,怎样做到提取这些暴露的方法呢?我能想到的方法是对要暴露的方法名制定一些规则,比如用RCTExport_作为前缀,然后用runtime方法class_getInstanceMethod取出所有方法名字,提取以RCTExport_为前缀的方法,但这样做恶心的地方是每个方法必须加前缀。React Native用了另一种黑魔法似的方法解决这个问题:编译属性__attribute__。 
在上述例子中我们看到模块方法里有句代码:RCT_EXPORT(),模块里的方法加上这个宏就可以实现暴露给JS,无需其他规则,那这个宏做了什么呢?来看看它的定义: 
Js代码 
  1. #define RCT_EXPORT(JS_name) __attribute__((used, section("__DATA,RCTExport" \  
  2. ))) static const char *__rct_export_entry__[] = { __func__, #JS_name }  



时间财富网为广大企业、商家、个人,提供平面设计、装修设计、建筑设计、起名改名、策划文案、网站建设、营销推广等服务。若您有类似需要,请点击立即发布项目

另,时间财富网上也有着各式各样的任务,无论您是拥有技能的专业人士,还是技术小白。都能在时间财富网上找到您能参与的项目。点击进入悬赏大厅

无论你有什么疑难杂症,威客们都能一一为您解决,点击进入:问答平台