RN调用iOS
本文要做的事情:iOS将推送数据,调用RN方法,进行数据传递。按步骤来,一定能成功的。。权威,文章会一直更新。
疑惑:不了解RN怎么办,没事,RN代码自有前端人员写。。
介绍:至于RN的介绍这里不多说了,,就为什么会出现iOS与RN的交互场景,这里阐述下。。
RN出现的目的就是
1.能快速迭代产品
2.有原生的用户体验 核心就是调用原生的API 但是他也不是无所不能的,总有需要iOS去传递数据到RN,RN拿到数据后做相应的操作。。比如推送,收到推送消息,iOS收到推送后,如何把数据传递RN,本文就推送这块重点说明,其余原理也肯定是一样的咯。
一:RN的iOS项目是怎么加载
1.没了解RN之前想法,(没看到具体RN项目的代码之前猜想)
(1).加载肯定和webView大同小异,一是加载本地文件,二是加载URL资源。。总之一句话,不是原生的,那只有去加载一个资源文件,即要么在本地,,要么是URL,不难理解。
(2).后来看看,还真就是这么回事
NSURL *jsCodeLocation;
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"]; // 本地
jsCodeLocation = [NSURL URLWithString:@"http://192.168.2.13:8081/index.ios.bunfsfsfdle?ffsf=ios&dev=fsfs"]; // URL
RCTRootView* rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"HelloWorld" initialProperties:nil launchOptions:nil];
self.view = rootView;
解释下:通过RCTRootView,加载一个资源文件(可本地,可URL)然后生成一个View,,把这个View赋值给当前显示控制器的view,
二.iOS如何回调RN,请看第二大题;(iOS将推送数据,传递给RN)
2.1:我们创建一个NotificationManager管理类,继承自RCTEventEmitter(RCT的事件源),遵守RCTBridgeModule(桥接模块)协议
2.2NotificationManager.m文件中,如图
注意:2018年04月26日,发现这个方法过期
[self.bridge.eventDispatcher sendAppEventWithName:@"didReceiveNotification" body:userInfo];
替换:
[self sendEventWithName:@"didReceiveNotification"
body:notification.userInfo];
注意:其实仔细看一下,,管理类提供了一个接口,
- (void)didReceiveNotification:(NSDictionary*)userInfo;处理数据
然后看图中的第二步:
[self.bridge.eventDispatchersendAppEventWithName:@"didReceiveNotification"body:userInfo];
解释一下:管理类中bridge(桥接)对象的eventDispatcher(事件调度器),发送了一个名字叫didReceiveNotification的事件,内容是userInfo,(也就是推送的字典)
2.3.APPDelegate中需要做的事情,由于笔者的rootViewController就是RN的数据,所以在
didFinishLaunchingWithOptions中就设置了
注意:注意:注意:重要的事情说三遍。
这句设置桥接的代码,在17年初的时候,用的时候还是可以的。最近17年11月份的时候。就会报错。。
1.原因:
@property (nonatomic,weak,readonly)RCTBridge *bridge;
RN在更新,讲这个属性变成readonly了,所以属性不能直接赋值了。
2.解决办法有三种:
1):改源码,将readonly删除,但是在清了缓存之后,代码又会还原变成readonly的,这应该是RN的保护机制吧,不能修改源码。( (我猜的) 不可行,
2):我们说OC是伪私有。因为我们有KVC啊,通过键值属性赋值。
[[NotificationManager manager] setValue:rootView.bridge forKey:@"bridge"];
解释一下:@"bridge"通过字符串名字去找对应的属性赋值。。完美解决。
3):运行时,runtime.。 获取通过类名找类对象,属性名去找属性,然后赋值一下。也能解决。
runtime代码,我懒得写了。。需要的自己试试。
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0 ; i < count; i ++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *ivarName = [NSString stringWithFormat:@"%s", name];
if ([ivarName isEqualToString:@"bridge"]) { // 如果属性名是 bridge
NSString *value =rootView.bridge; // 赋值呗
}
[self setValue:value forKey:[NSString stringWithFormat:@"%s", name]];
}
free(ivars);
大致就是这样了。
2.4.在applicationDidReceiveRemoteNotification中,通知管理类处理消息
iOS10新增:
其实仔细看看把:实际代码没有多少的,但是又不能提供demo,毕竟是推送。。
总结一下:1.其实就是在RCTRootView创建好后,通过设置桥接对象,将事件处理交给NotificationManager处理
2.在收到推送时,讲数据UserInfo让NotificationManager处理,去调用RN,事件名是DidRecieveNotification,body是UserInfo
3.notificationManager的具体创建,详情在2.1
2.5 最后附加下RN那边是如何处理DidRecieveNotification,和UserInfo数据的
顾名思义:第一个箭头事件名,,第二个箭头text就是Userinfo的内容,然后RN拿到UserInfo的数据保存了起来,,,RN代码看不懂没事,流程明白了就行了:看此图的第一行代码,读句子:设备事件源增加一个名字叫DidrecieveNotification的监听;
另外:有小伙伴说我没有说清楚,怎么把相应的类目导入到RN模块。这里增加下
大总结:其实就是iOS端设置了桥接内容,将收到的通知内容传递给RN,然后RN监听有没有对应Name的事件名,有的话就处理,,希望能够帮到你,,如有说的不对的地方,欢迎指正,楼主联系方式处有楼主联系方式,
最后附加一个rn调用iOS的文章:RN调用iOS 这两个文章结合,没有解决不了的RN交互问题
如果你喜欢这篇文章,或者有任何疑问,可以扫描第一个二维码,加楼主好友哦
也可以扫第二个二维码,关注楼主个人微信公众号。这里有很多生活,职业,技术相关的文章哦。欢迎您的到来。
微信号:
公众号