美文网首页
ReactNative与原生(IOS)页面跳转和通信(一))

ReactNative与原生(IOS)页面跳转和通信(一))

作者: 冲云简 | 来源:发表于2020-01-07 12:44 被阅读0次

    序言: React Native无论是在社区和应用程度上,在国内外是十分广泛和普及的。最近总结了下RN关于IOS和Android的通信,希望大家喜欢,文章末尾有github的Demo地址。本文参照官网来写:地址跳转

    • 一、IOS通信——直接调用,Callback,Promise
      你可以在JavaScript通过NativeModules调用原生组件,原生方法,通过NativeEventEmitter进行添加事件。
      在ReactNative中,一个原生模块就是通过“RCTBridgeModule”协议的 Objective-C 类,为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏,这个宏也可以添加一个参数用来指定在 JavaScript 中访问这个模块的名字。如果你不指定,默认就会使用这个 Objective-C 类的名字。
      声明通过RCT_EXPORT_METHOD()宏来实现要给JavaScript导出的方法。

    RCT_EXPORT_METHOD 支持所有标准 JSON 类型,包括:

    • string (NSString)
    • number (NSInteger, float, double, CGFloat, NSNumber)
    • boolean (BOOL, NSNumber)
    • array (NSArray) 可包含本列表中任意类型
    • object (NSDictionary) 可包含 string 类型的键和本列表中任意类型的值
    • function (RCTResponseSenderBlock)

    除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个 JSON 值并转换到原生 Objective-C 类型或类。

    下面看代码:
    原生实现:
    xxx.h

    #import <Foundation/Foundation.h>
    #import <React/RCTBridgeModule.h>
    ///添加RCTBridgeModule协议
    @interface LiveModule : NSObject<RCTBridgeModule>
    
    @end
    

    xxx.m ——实现导出给JavaScript的方法。包含Callback和Promise回调

    @implementation LiveModule
    
    RCT_EXPORT_MODULE();
    
    ///直接调用原生方法
    RCT_EXPORT_METHOD(pushLiveViewController: (NSString *)str) {
      ///rn和原生桥接是异步的,所以需要对UI操作必须在主线程。
      dispatch_async(dispatch_get_main_queue(), ^{
        UINavigationController *nav = (UINavigationController *)AppDelegate.shareAppDelegate.window.rootViewController;
        ViewController *vc = [[ViewController alloc] init];
        [nav presentViewController:vc animated:false completion:nil];
      });
    }
    
    ///callback回调
    RCT_EXPORT_METHOD(findEvents: (RCTResponseSenderBlock)callback) {
      callback(@[[NSNull null], CALL_VALUE]);
    }
    
    ///promise回调
    RCT_EXPORT_METHOD(liveValue: (BOOL)valueI
                      findEventsWithResolver: (RCTPromiseResolveBlock)resolve
                      rejecter:(RCTPromiseRejectBlock)reject) {
      
      if (valueI == YES) {
        resolve(PROMISE_VALUE);
      }else {
        NSError *error = nil;
        reject(@"error", @"This is error!", error);
      }
    }
    

    JavaScript通过NativeModules调用原生方法

    const liveModule = NativeModules.LiveModule;
    ///直接调用
    liveModule.pushLiveViewController('xxx');
    
    //callback方式
    liveModule.findEvents((error, value) => {
          this.setState({
            callText: value,
          });
        });
    
    //promise方式
    liveModule
          .liveValue(true)
          .then(value => {
            this.setState({
              promiseText: value,
            });
          })
          .catch(error => {
            console.log(error);
          });
    

    原生给JavaScript发送事件
    最好的方法是继承RCTEventEmitter,实现suppportEvents方法并调用self sendEventWithName:。

    @interface LiveEventEmitter : RCTEventEmitter <RCTBridgeModule>
    ///给js端发送事件
    - (void)sendMessageToRN: (NSDictionary *)dict eventName:(NSString *)name;
    @end
    
    @interface LiveEventEmitter()
    
    @property(nonatomic, strong)NSArray * nameArrays;
    @end
    
    @implementation LiveEventEmitter
    RCT_EXPORT_MODULE();
    
    /// 重写方法,添加事件名
    -(NSArray<NSString *> *)supportedEvents {
      return self.nameArrays;
    }
    //重写方法,单例获取bridge。如果不重写bridge为nil
    + (id)allocWithZone:(struct _NSZone *)zone {
      static LiveEventEmitter *live = nil;
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
        live = [super allocWithZone:zone];
      });
      
      return live;
    }
    
    ///发送事件给js
    - (void)sendMessageToRN: (NSDictionary *)dict eventName:(NSString *)name {
      [self sendEventWithName:name body:dict];
    }
    
    - (NSArray *)nameArrays {
      if (_nameArrays == nil) {
        _nameArrays = @[@"EventName"];
      }
      return _nameArrays;
    }
    
    @end
    
    

    JavaScript订阅事件

    //在componentDidMount()中订阅事件
    const eventEmitter = new NativeEventEmitter(NativeModules.LiveEventEmitter);
          this.listener = eventEmitter.addListener('EventName', value => {
            this.setState({
              touchText: value.message,
            });
          });
    

    Demo地址https://github.com/JoyceRao/React-Native-RNNativeCommunication

    参考链接https://www.jianshu.com/p/ea3484f54643

    相关文章

      网友评论

          本文标题:ReactNative与原生(IOS)页面跳转和通信(一))

          本文链接:https://www.haomeiwen.com/subject/xusractx.html