rn源码ios_ReactNative马甲包与iOS原生交互方式汇总,学会轻松上架App Store

最近用RN开发SDK,涉及RN与iOS各种交互。

有些交互比如用iOS原生切换多个RN页面,以及iOS调用RN的方法,按照网上的方法调不通,一度不知如何是好,网上资料比较少。

于是自己看RN源码分析得出一些方法。 如有问题欢迎指正,有更好的思路方法欢迎分享。

一、 iOS 调用ReactNative

1,打开一个ReactNative页面

2,多个ReactNative页面切换(尽量在RN内实现)

3,iOS调用RN(分是否传参数)

二、ReactNative调用iOS

1,无参数无回调

2,有多个参数

3,有回调

4,有多个参数多个回调

说明:

1,Demo: RNInteractionWithIOS

2,ReactNative版本:

"react": "16.4.1",

"react-native": "0.56.0"

一、 iOS 调用ReactNative

1,打开一个ReactNative页面

比如react-native init RNInteractionWithiOS 创建一个应用之后就会自动在 RNInteractionWithiOS->ios->RNInteractionWithiOS->AppDelegate.m中生成打开一个ReactNative页面的代码。核心代码如下:

NSURL *jsCodeLocation;

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation

moduleName:@"RNInteractionWithiOS"

initialProperties:nil

launchOptions:launchOptions];

rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

UIViewController *rootViewController = [UIViewController new];

rootViewController.view = rootView;

self.window.rootViewController = rootViewController;

[self.window makeKeyAndVisible];

2,多个ReactNative页面切换(尽量在RN内实现)

这个有点难度,当时还研究了半天,几乎没有资料可参考RN核心代码: 在index.js中

AppRegistry.registerComponent("App", () => App);

AppRegistry.registerComponent("App2", () => App2);

iOS中OC核心代码:设置RCTBridge的代理

实现代理方法- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge;

最关键的:通常情况下我们会使用initWithBundleURL创建一个RCTRootView,此处必须使用initWithBridge创建RCTRootView

#import "ViewController.h"

#import

#import

@interface ViewController ()

@property (nonatomic, strong) RCTBridge *bridge;

@end

@implementation ViewController

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {

return [NSURL URLWithString:@"http://127.0.0.1:8081/index.bundle?platform=ios"];// 模拟器

}

- (void)viewDidLoad {

[super viewDidLoad];

_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];

}

#define RNBounds CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width-50, UIScreen.mainScreen.bounds.size.height/2.f)

- (IBAction)openRNOne {

[self removeRNPage];

[self loadRNView:@"App"];

}

- (IBAction)openRNTwo {

[self removeRNPage];

[self loadRNView:@"App2"];

}

- (IBAction)removeRNPage {

[self.view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

if ([obj isKindOfClass:[RCTRootView class]]) {

[obj removeFromSuperview];

return;

}

}];

}

- (void)loadRNView:(NSString *)moduleName {

RCTRootView *rnView2 = [[RCTRootView alloc] initWithBridge:_bridge

moduleName:moduleName

initialProperties:nil];

rnView2.bounds = RNBounds;

rnView2.center = self.view.center;

[self.view addSubview:rnView2];

}

3,iOS调用RN(分是否传参数)RN核心代码

componentWillMount() {

DeviceEventEmitter.addListener('EventInit', (msg) => {

let receive = "EventInit: " + msg;

console.log(receive);

this.setState({notice: receive});

});

DeviceEventEmitter.addListener('EventLogin', (msg) => {

let receive = "EventLogin: " + msg;

console.log(receive);

this.setState({notice: receive});

});

}iOS核心代码:创建的iOS交互类要引用#import 和#import ,继承RCTEventEmitter,并遵守RCTBridgeModule

很关键的:交互类要设置bridge为当前RCTRootView的bridge,[[ReactInteraction shareInstance] setValue:rnView.bridge forKey:@"bridge"];

ReactInteraction.h文件

#import

#import

#import

@interface ReactInteraction : RCTEventEmitter

+ (instancetype)shareInstance;

- (void)init:(NSString *)parameter;

- (void)login;

@end

ReactInteraction.m文件

#import "ReactInteraction.h"

#define INIT @"EventInit"

#define LOGIN @"EventLogin"

@implementation ReactInteraction

static ReactInteraction *instance = nil;

RCT_EXPORT_MODULE();

+ (instancetype)shareInstance {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

instance = [[self alloc] init];

});

return instance;

}

- (NSArray *)supportedEvents

{

return @[INIT,LOGIN];

}

RCT_EXPORT_METHOD(init:(NSString *)msg) {

[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter"

method:@"emit"

args:@[INIT, msg]

completion:NULL];

}

RCT_EXPORT_METHOD(login) {

[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter"

method:@"emit"

args:@[LOGIN]

completion:NULL];

}

@end

二、ReactNative调用iOSRN核心代码:

import {NativeModules} from 'react-native';

const NativeInteraction = NativeModules.NativeInteraction;

OS核心代码:注意点1:RCT_EXPORT_METHOD与RCT_REMAP_METHOD宏定义的使用区别(个人总结,有不对请指正)

RCT_EXPORT_METHOD:用于仅有一个参数或回调

RCT_REMAP_METHOD:用于有多个参数或(和)多个回调

(了解更多可以看RN宏定义源码1,下面 贴出关键两句)

注意点2:iOS回调方式有两种

callback(@[jsonString]); ((RCTPromiseResolveBlock)resolver)

Promise方式:_resolveBlock(@[jsonString]); ((RCTResponseSenderBlock)callback) (了解更多看RN源码2)

源码1:

#define RCT_REMAP_METHOD(js_name, method) \

_RCT_EXTERN_REMAP_METHOD(js_name, method, NO) \

- (void)method RCT_DYNAMIC;

#define RCT_EXPORT_METHOD(method) \

RCT_REMAP_METHOD(, method)

源码2:

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

typedef void (^RCTResponseErrorBlock)(NSError *error);

typedef void (^RCTPromiseResolveBlock)(id result);

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

1,无参数回调

RN核心代码:

NativeInteraction.RNTransferIOS();

iOS核心代码:

RCT_EXPORT_METHOD(RNTransferIOS) {

NSLog(@"RN调用iOS");

}

2,有多个参数

RN核心代码:

RCT_EXPORT_METHOD(RNTransferIOSWithParameter:(NSString *)logString) {

NSLog(@"来自RN的数据:%@",logString);

}

3,有回调

RN核心代码:

NativeInteraction.RNTransferIOSWithCallBack((data) => {

this.setState({notice: data});

});

iOS核心代码:

RCT_EXPORT_METHOD(RNTransferIOSWithCallBack:(RCTResponseSenderBlock)callback) {

callback(@[[NSString stringWithFormat:@"来自iOS Native的数据:%@",TestNativeJsonData]]);

}

4,有多个参数多个回调RN核心代码:

NativeInteraction.RNTransferIOSWithParameterAndCallBack('rndata1','rndata2').then(result =>{ let jsonString = JSON.stringify(result); this.setState({notice: jsonString}); }).catch(error=>{ });

iOS核心代码:{ RCTPromiseResolveBlock _res

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值