iOS开发 React Native与iOS交互汇总
RN简介
React Native 是一个使用React和应用平台的原生功能来构建 Android 和 iOS 应用的开源框架。起源于faceBbook内部,2013开源。
React Native 组件就是对原生视图的封装,因此使用 React Native 编写的应用外观、感觉和性能与其他任何原生应用一样。
RN坏境搭建
iOS必须安装的依赖有:Node、Watchman、Xcode 和 CocoaPods。
可以参考RN官网:https://reactnative.cn/docs/environment-setup
iOS 调用React Native
1,打开一个React Native页面
比如react-native init RNInteractionWithiOS 创建一个应用之后就会自动在 RNInteractionWithiOS->ios->RNInteractionWithiOS->AppDelegate.m
中生成打开一个React Native页面的代码。核心代码如下:
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];
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<React/RCTBridgeModule.h>
和#import <React/RCTEventEmitter.h>
,继承RCTEventEmitter
,并遵守RCTBridgeModule
- 很关键的:交互类要设置
bridge
为当前RCTRootView的bridge
,[[ReactInteraction shareInstance] setValue:rnView.bridge forKey:@"bridge"];
ReactInteraction.h文件
#import <Foundation/Foundation.h> #import <React/RCTBridgeModule.h> #import <React/RCTEventEmitter.h> @interface ReactInteraction : RCTEventEmitter <RCTBridgeModule> + (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<NSString *> *)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
React Native调用iOS
RN核心代码:
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:
源码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
RCT_EXPORT_METHOD(navigate:(NSString*)page parameter:(NSDictionary *)dic callback:(RCTResponseSenderBlock )callback){ //主线程处理UI事件 dispatch_async(dispatch_get_main_queue(), ^{ //跳转类型 if ([page isEqualToString:@"ShoppingMall"]){ //九九老年商城 WeiMengWebVC *weiMengWebVC = [[WeiMengWebVC alloc] init]; [dic setValue:@"1" forKey:@"type"]; weiMengWebVC.dic = dic; [[UIViewController topViewController].navigationController pushViewController:weiMengWebVC animated:YES]; } }
typedef void (^RCTResponseSenderBlock)(NSArray *response); typedef void (^RCTResponseErrorBlock)(NSError *error); typedef void (^RCTPromiseResolveBlock)(id result); typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error