react-native调用ios native方法-回调

上一篇中介绍了使用react-native调用ios native方法,在真实的使用场景中,不仅仅只是调用下Native的方法,还需要对结果进行处理,Native处理完之后返回结果再回调会JavaScript中进行操作和处理。
这样就需要使用JavaSctipt的回调函数,对结果进行处理。在React Native中Object-c有两种方式的回调:RCTReponseSenderBlockPromises

RCTReponseSenderBlock

在JavaScript和Object-C的参数列表,有一类参数叫做RCTReponseSenderBlock对于JavaScript的Function,这个就是JavaScript调用Object-C的Callback(回调函数)。

  • RCTReponseSenderBlock是在RCTBridgeModule.h定义的block.
    完整的定义:

typedef void (^RCTResponseSenderBlock)(NSArray *response);

RCTReponseSenderBlock定义个一个Object-C Bridge的操作,返回给JavaScript一个callback的方法。

他的参数是一个NSArray。其中第一个参数是error代表着错误信息,如果没有错误传入null,后面的参数传入自定义的内容。
具体实例:
先给UIAlertView添加两个按钮,在点击按钮之后使用RCTResponseSenderBlock返回JavaScript。
先实现UIAlertViewDelegate

@interface RNIOSAlert : NSObject<RCTBridgeModule,UIAlertViewDelegate>
@end

定义一个变量用来保存参数:

@implementation RNIOSAlert{
 RCTResponseSenderBlock _alertCallback;
}
@end

clickedButtonAtIndex方法中处理结果并调用回调函数:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
 if (buttonIndex==0) {
  _alertCallback(@[@"cancel",]);
 }else{
  _alertCallback(@[[NSNull null],@1]);
 }
}

最后定义带有回调参数的Native方法:

RCT_EXPORT_METHOD(showAlertAndCallback:(RCTResponseSenderBlock)callback){
 _alertCallback=callback;
 UIAlertView * alertView=[[UIAlertView alloc] initWithTitle:@"react-native" message:@"是否继续?" delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:@"继续",nil];
 [alertView show];


}

最在JavaScript中调用Native方法,并处理回调:

_alertCallback() {

    RNIOSAlert.showAlertAndCallback(function (err,datas) {
      if (err) {
        console.warn('err','已取消');
      } else {
        console.warn('data','请继续');
      }

    });
  }

每次关闭UIAlertView都可以看到JavaScript处理的结果。

Promises

PromisesES6中的特性,它的目的是统一为JavaScript提供异步编程的接口,避免Callback地狱,解决了Callback的层层嵌套。更加容易的对异步操作进行控制。
在React Native中对Promises有很完善的支持,调用Object-C 的Native方法的时候,也可以Promise的方式让代码执行从Object-C 回到JavaScript中。
先看Promises的两个状态。

  • Resolve和Reject

ResolveReject分量是Promise的两种状态,表示已解决和已拒绝,Resolve是正常的执行结果,而Reject会触发catch操作。
在Object-C与之相对应的是:RCTPromiseResolveBlockRCTPromiseRejectBlock,两个都是定义好的Object-C bridge。

RCTPromiseResolveBlock的实现:

typedef void (^RCTPromiseResolveBlock)(id result);

id为参数,当然传参必须是Object-c和JavaScript定义好的参数。
RCTPromiseRejectBlock的实现:

typedef void (^RCTPromiseRejectBlock)(NSString *code,NSString *message,NSError *error);

RCTPromiseRejectBlock使用了NSError,还可以传入自定义的code以及message

  • 使用Promise实现回调
    首先要定义两个变量用来保存参数:

@implementation RNIOSAlert{
 RCTPromiseResolveBlock _resolveBlock;
 RCTPromiseRejectBlock _rejectBlock;
}

在定义提供给JavaScript调用的Native函数:

RCT_REMAP_METHOD(alertUserPromise,resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)reject){
 _resolveBlock=resolver;
 _rejectBlock=reject;
 UIAlertView * alertView=[[UIAlertView alloc] initWithTitle:@"react-native" message:@"使用Promise?" delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:@"继续",nil];
 [alertView show];
}

这里使用RCT_REMAP_METHOD宏定义Native,他的第一个参数是方法名,后面的参数是方法的实现,在JavaScript调用Promise时并不需要在方法名中体现。
处理结果并使用回调:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
 if (buttonIndex==0) {
  NSError * err=[NSError errorWithDomain:@"test" code:0 userInfo:nil];
  _rejectBlock(@"0",@"cancel",err);
 }else{
  _resolveBlock(@[@1]);
 }
}

JavaScript中调用该方法:

_alertUsePromise() {
    RNIOSAlert.alertUserPromise().then((datas)=> {
      console.warn('data',datas);
    }).catch((err)=> {
      console.warn('err',err);
    });
  }

这里的then处理的是Resovle状态的结果,而catch处理的是Reject状态的结果。
也可以使用async/await实现

async _alertPromise() {
    try {
      var datas = await RNIOSAlert.alertUserPromise();
      console.warn('data',datas);
    } catch (e) {
      console.warn('err',e);
    }
  }

async/await是两个关键词,用来把Promises的思想融入到语言本身。使用他们就不再需要写catch这样的伪同步的代码,直接使用try/catch/return这样的关键词就可以了.
Promises对于回调的使用很便利,尽量避免了JavaScript的回调地狱。

代码地址:https://github.com/jjz/react-...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom