iOS原生项目(Objective-C)集成React Native(0.57.3版本)图文教程–(1)基本环境
iOS原生项目(Objective-C)集成React Native(0.57.3版本)图文教程–(2)集成过程
一个RNDemo(React Native 0.57.3 + ES6)实现(包含RN与原生相互跳转和通信)
iOS原生界面与RN界面互调及传值
iOS端
:
#import
.RCTBridgeModule
协议.RCT_EXPORT_MODULE()
写调用的方法.RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(openNativeVC) {
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
UINavigationController *rootNav = delegate.navigationController;
ZYViewController *nativeVC = [[ZYViewController alloc] init];
[rootNav pushViewController:nativeVC animated:YES];
});
}
RN端
:
NativeModules
模块.var nativeModule = NativeModules.OpenNativeModule;
//跳转到原生界面
jumpToNative() {
nativeModule.openNativeVC()
}
所传参数可以是已知的数据类型,不过最好用NSDictionary
和NSArray
来传,其实原理就是RN
那边传递个json
过来,在RN
中json
也是个对象
RCT_EXPORT_METHOD(openNativeVCWithParams:(NSDictionary *)params) {
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
UINavigationController *rootNav = delegate.navigationController;
ZYViewController *nativeVC = [[ZYViewController alloc] init];
nativeVC.params = params;
[rootNav pushViewController:nativeVC animated:YES];
});
}
//跳转到原生界面
jumpToNativeWithParams() {
var params = {"title": "定位地址: 北京"};
nativeModule.openNativeVCWithParams(params)
}
#import "ViewController.h"
@interface ZYLoginViewController : UIViewController
@property (nonatomic, copy) void(^loginBlock) (NSArray* resultArr);
@end
RCT_EXPORT_METHOD(loginState:(NSString *)state callback:(RCTResponseSenderBlock)callback) {
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
ZYLoginViewController *login = [[ZYLoginViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:login];
[delegate.navigationController presentViewController:nav animated:YES completion:nil];
//登录成功后,login控制器就可以调用block,进行回调了
login.loginBlock = ^(NSArray *resultArr) {
callback(@[[NSNull null], resultArr]);
};
});
}
- (void)doLogin {
self.loginBlock(@[@"zhouyu", @"123456"]);
[self dismiss];
}
- (void)dismiss {
[self dismissViewControllerAnimated:YES completion:nil];
}
React Native中文网: 和原生端通信
React Native中文网: 回调函数及通信
主要分两种情况: 一种是原生界面向下级RN界面传值; 另一种是原生界面向上级RN界面传值
这种情况不能用NativeEventEmitter
结合iOS的通知来实现传值,因为通知是现有监听者再有发送者,向下级RN界面传值,这种方式有可能下级RN页面还没加载出来,通知就已经发送了,导致下级RN页面获取不到值
可以利用加载js的budle文件时,利用initialProperties参数进行传值
NSDictionary *properties = @{@"name": @"zhangsan"};
NSURL *url = [NSURL URLWithString:@"http://localhost:8081/NewIndex.bundle?platform=ios&dev=true"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:url moduleName:@"RNDemo" initialProperties:properties launchOptions:nil];
self.view = rootView;
此种情况可以使用RN的NativeEventEmitter
结合iOS的通知来实现传值
#import
#import
@interface NativeToRNEventEmitter : RCTEventEmitter <RCTBridgeModule>
+ (instancetype)shareInstance;
@end
#import "NativeToRNEventEmitter.h"
@interface NativeToRNEventEmitter()
@property (nonatomic,assign)BOOL hasListeners;
@end
@implementation NativeToRNEventEmitter
+ (instancetype)shareInstance {
static NativeToRNEventEmitter *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[NativeToRNEventEmitter alloc] init];
});
return instance;
}
RCT_EXPORT_MODULE();
//init方法中使用NSNotificationCenter监听iOS端要发送事件的操作
- (instancetype)init {
if (self = [super init]) {
[self registerNotifications];
}
return self;
}
//在NSNotification对应的通知方法中将事件发送给RN
- (void)registerNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendCustomEvent:)
name:@"CustomEventNameNotifation"
object:nil];
}
- (void)sendCustomEvent:(NSNotification *)notification {
// NSString *eventName = notification.userInfo[@"name"];
if (self.hasListeners) {
[self sendEventWithName:@"CustomEventName" body:@{@"name": @"东皇大厦"}];
}
}
#pragma RCTEventEmitter
//重写supportedEvents方法,在这个方法中声明支持的事件名称
- (NSArray<NSString *> *)supportedEvents {
return @[@"CustomEventName"];
}
// 在添加第一个监听函数时触发
-(void)startObserving {
self.hasListeners = YES;
}
-(void)stopObserving {
self.hasListeners = NO;
}
@end
var nativeToRNEventModule = NativeModules.NativeToRNEventEmitter;
componentDidMount() {
var eventEmitter = new NativeEventEmitter(nativeToRNEventModule);
this.listener = eventEmitter.addListener("CustomEventName", (result) => {
alert("监听到通知事件" + result);
this.setState({
add: result.name
});
})
}
componentWillUnmount() {
this.listener && this.listener.remove();
}