美文网首页
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