reactnative ios(详解React Native与IOS端之间的交互)
reactnative ios
详解React Native与IOS端之间的交互目录
- 前置准备
- RN 传值给 iOS
- 方法 1 正常传值给原生
- 方法 2 传递回调函数
- 方法 3 获取 promise 回调
- 方法 4 获取 promise 的同步方式
- iOS 传值给 RN 端
- 初始的数据提供
- 添加监听事件
- 总结
首先最好了解一点关于 oc 的语法知识
1.创建声明文件nativeModule.h
#import <Foundation/Foundation.h> #import <React/RCTBridgeModule.h> @interface nativeModule : NSObject <RCTBridgeModule> @end
2.创建文件nativeModule.m
#import <Foundation/Foundation.h> #import "nativeModule.h" @interface nativeModule () @end @implementation nativeModule @end
这是添加完文件后的结构目录
关于 interface 的区别:
.h里面的@interface,它是供其它Class调用的。它的@property和functions,都能够被其它Class“看到”(public)
而.m里面的@interface,在OC里叫作Class Extension,是.h文件中@interface的补充。但是.m文件里的@interface,对外是不开放的,只在.m文件里可见(private)
因此,我们将对外开放的方法、变量放到.h文件中,而将不想要对外开放的变量放到.m文件中(.m文件的方法可以不声明,直接用)。
RN 传值给 iOS方法 1 正常传值给原生
在 .m 文件中添加方法:
// 省略上面的代码 @implementation nativeModule // 这句代码是必须的 用来导出 module, 这样才能在 RN 中访问 nativeModule这个 module RCT_EXPORT_MODULE(); // 接收字符串 RCT_EXPORT_METHOD(addHelloWord:(NSString *)name location:(NSString *)location) { NSLog(@"%@,%@", name, location); } @end
RN 代码:
import { Button, NativeModules } from 'react-native' const { nativeModule } = NativeModules <Button title={'传 2 个参数给 native'} onPress={() => { nativeModule.addHelloWord('你的名字', '位置:浙江') }}/>
点击此按钮的作用,就是将 '你的名字', '位置:浙江' 这 2 个字符串传递到了原生端
方法 2 传递回调函数
在 .m 文件中添加:
// 只接受一个参数——传递给 JavaScript 回调函数的参数数组。 RCT_EXPORT_METHOD(checkIsRoot:(RCTResponseSenderBlock)callback) { NSArray *array = @[@"string", @"number"]; callback(array); }
在 RN 中添加代码:
<Button title={'js 传一个回调给 native,回调中收到一个数组'} onPress={() => { nativeModule.checkIsRoot((str: string, num: string) => { console.log(str, num) }) }}/>
这是在 RN 中 给原生端传递了一个回调函数,用来解决,部分操作完成后的回调, ** 如果 callback 多次调用 RN 会报错 **
方法 3 获取 promise 回调
在 .m 文件中添加代码:
@interface nativeModule () @property (nonatomic) RCTPromiseResolveBlock normalResolve; @property (nonatomic) RCTPromiseRejectBlock normalReject; @property (nonatomic) NSInteger num; @end // 这是一个计时器 -(void)startTime: (NSArray*) data{ NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { NSArray *events =@[@"Promise ",@"test ",@" array"]; if (events) { self.normalResolve(events); [timer invalidate]; } else { [timer invalidate]; NSError *error=[NSError errorWithDomain:@"我是回调错误信息..." code:101 userInfo:nil]; self.normalReject(@"no_events", @"There were no events", error); } }]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } // 回调给RN的参数,回调的错误信息 RCT_EXPORT_METHOD(getHBDeviceUniqueID: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { // 要执行的任务 self.normalResolve = resolve; self.normalReject = reject; [self performSelectorOnMainThread:@selector(startTime:) withObject: [NSArray arrayWithObjects: @"1", @"2", nil] waitUntilDone:YES]; }
在 RN 中添加代码:
<Button title={'native传一个 promise 给 JS'} onPress={() => { nativeModule.getHBDeviceUniqueID().then((arr: string[]) => { console.log('resolve', arr) }).catch((err: string) => { console.error(err) }) }}/>
nativeModule.getHBDeviceUniqueID 的执行他是一个 promise,可以获取原生端的回调, 其实和方法 2 差不多
方法 4 获取 promise 的同步方式
在 .m 文件中添加:
// 这是一个计时器2 -(void)startTime2: (NSArray*) data{ NSLog(@"data%@",data); NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { NSLog(@"%d", (int)self.num); self.num = self.num + 1; NSLog(@"%d", (int)self.num); if (self.num > 4) { [timer invalidate]; NSLog(@"end"); self.normalResolve(data); } }]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } // RCT_REMAP_METHOD 与RCT_EXPORT_METHOD相同,但是该方法是在JS线程上从JS同步调用的,可能会返回结果。 // 同步可能会有性能问题 建议除了 promise 以外都别使用 RCT_REMAP_METHOD(findEvents, findEventsWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { self.normalResolve = resolve; self.normalReject = reject; self.num = 0; [self performSelectorOnMainThread:@selector(startTime2:) withObject: [NSArray arrayWithObjects: @"1", @"2", nil] waitUntilDone:YES]; }
在 RN 端添加代码:
<Button title={'native传一个 promise 给 JS2'} onPress={() => { nativeModule.findEvents().then((arr: string[]) => { console.log('resolve', arr) }).catch((err: string) => { console.error(err) }) }}/>
方法 4 和方法 3 大体一致,但是有一点不同,就是 RCT_REMAP_METHOD 使用此方法会将代码变成同步状态
iOS 传值给 RN 端初始的数据提供
在 appDelegate.m 文件中添加代码:
NSArray *imageList = @[@"http://foo.com/bar1.jpg" alt="reactnative ios(详解React Native与IOS端之间的交互)" border="0" />
在 RN 端写入:
// 重写 APP , images就是 iOS 提供的数据,这里我们通过 context 来传递数据 export default class App extends React.Component<{ images: string[] }> { render() { return <NativeProps.Provider value={this.props.images}> <AppContainer/> </NativeProps.Provider> } } // 在 hooks 里简单的使用 const images = useContext(NativeProps); <Text>这是从 native 端传来的初始数据{JSON.stri.jpg" alt="reactnative ios(详解React Native与IOS端之间的交互)" border="0" />
添加监听事件
在 .m 文件中添加代码:
// 可供监听的事件名称 - (NSArray<NSString *> *)supportedEvents { return @[@"EventReminder"]; } RCT_EXPORT_METHOD(postNotificationEvent:(NSString *)name) { NSLog(@"calendarEventReminderReceived"); [self sendEventWithName:@"EventReminder" body:@{@"name": name}];; } - (void)calendarEventReminderReceived:(NSNotification *)notification { // 这是官网的例子 NSLog(@"calendarEventReminderReceived"); NSString *eventName = notification.userInfo[@"name"]; [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}]; } RCT_EXPORT_METHOD(Send){ NSDictionary *dict = @{@"name" : @"veuimyzi"}; NSNotification *notification = [[NSNotification alloc] initWithName:@"EventReminder" object:nil userInfo:dict] ; [self calendarEventReminderReceived:notification]; }
在 RN 中添加代码:
const ManagerEmitter = new NativeEventEmitter(nativeModule) const [msg, setMsg] = useState([]) // hooks 中的使用,类似于 componentDidMount 生命周期 useEffect(() => { const subscription = ManagerEmitter.addListener( 'EventReminder', (reminder) => { setMsg(prevState => { return prevState.concat(reminder.name) }) console.log('这是监听的EventReminder事件回复', reminder.name) } ) return () => { subscription.remove() } }, []) <Button title={'js 监听事件,让 native 给 js 发通知'} onPress={() => { nativeModule.postNotificationEvent('test') }}/> <Button title={'js 监听事件,让 native 给 js 发通知 send'} onPress={() => { nativeModule.Send() }}/> { msg.map((item, index) => { return <Text key={item + index}>item:{item}</Text> }) }
关于 postNotificationEvent 方法是属于最简单的使用, 在原生端调用 sendEventWithName 就可以传递数据给 RN 的监听
而另一个方法 Send 和 calendarEventReminderReceived ,一个是来自于官网的实例 讲的是从 NSNotification获取数据, Send 是传递数据给 calendarEventReminderReceived
关于监听的优化, 这个官网上也有,有空可以看下,就是在 .m 文件中添加下列代码:
@implementation nativeModule { bool hasListeners; // 一个局部变量 } -(void)startObserving { hasListeners = YES; } -(void)stopObserving { hasListeners = NO; } // 在发送监听的添加判断,如果有监听才发送,有效减少桥接代码的调用 if (hasListeners) { [self sendEventWithName:@"EventReminder" body:@{@"name": name}];; }
上述代码的库: https://github.com/Grewer/learn-rn
关于原生端和 RN 端的交互基本就是这些了,当然原生端还有更多,更复杂的操作,比如进程什么的,如果想写桥接方法,这个也会碰到很多,不过掌握了上面这些,对于一些三方 SDK 的调用是够用了
以上就是详解React Native与IOS端之间的交互的详细内容,更多关于React Native与IOS端之间的交互的资料请关注开心学习网其它相关文章!
- react动态添加组件属性(react使用antd的上传组件实现文件表单一起提交功能完整代码)
- reacthooks基础使用(React 小技巧教你如何摆脱hooks依赖烦恼)
- react怎么使用父组件(关于antd tree和父子组件之间的传值问题react 总结)
- react的事件绑定(React事件绑定的方式详解)
- react子组件的动态参数(浅谈React Component生命周期函数)
- react 的事件机制(React如何优雅的捕获异常)
- vscode react jsx语法 开发环境(React-vscode使用jsx语法的问题及解决方法)
- reactnative混合开发教程(教你使用vscode 搭建react-native开发环境)
- vue中的ref(Vue3.0中Ref与Reactive的区别示例详析)
- react绑定详解(React列表栏及购物车组件使用详解)
- react跳转页面并传参数(react 跳转后路由变了页面没刷新的解决方案)
- linux虚拟内存实现需要哪六种机制(解析Linux高性能网络IO和Reactor模型)
- react hooks详解(React Hooks使用常见的坑)
- react怎样实现响应式计算属性(深入浅析React中diff算法)
- react基础知识入门(浅谈React 的引入)
- react路由原理解析(React配置子路由的实现)
- 袁冰妍终于接到新剧,饰演反追男主,看到合作演员 眼光果然毒辣(袁冰妍终于接到新剧)
- 记忆中的台词(记忆中的台词)
- 袁冰妍轧戏 拍《琉璃》的同时还在拍《将夜》,难怪被骂演技差(拍琉璃的同时还在拍将夜)
- 刚红就耍大牌,《琉璃》角色滤镜碎一地,心疼工作人员(琉璃角色滤镜碎一地)
- 袁冰妍郑业成这对可以处,有脸红情话他们是真的敢说(袁冰妍郑业成这对可以处)
- 《祝卿好》台词又土又甜,就喜欢这么直接的恋爱(祝卿好台词又土又甜)
热门推荐
- mysqldecimal类型转换(mysql中decimal数据类型小数位填充问题详解)
- 织梦网站栏目管理和内容发布(使用DEDE织梦计划任务功能定时更新首页)
- wdc真正的底层公链(LiteSpeed服务器用htaccess的防盗链代码)
- laravel终止函数执行(laravel 输出最后执行sql 附:whereIn的使用方法)
- wampserver安装报错(安装wampserver提示丢失MSVCR100.dll的解决方法)
- python复杂的验证码处理(Python 通过打码平台实现验证码的实现)
- laravel的验证规则(解决在Laravel 中处理OPTIONS请求的问题)
- sql server案例(SQL Server作业报错特殊案例分析)
- docker-compose 开发代码(Docker Compose多容器部署的实现)
- windows服务器安全设置经验(Windows 2016 服务器安全设置)