- Unable to find a specification for 'boost-for-react-native' depended upon by
Folly
#18085
解决的方案: pod update
- React Native报错:Application XXX has not been registered.
RN 与原生之间的通信
从原生组件传递属性到React Native
我们使用RCTRootView将React Natvie视图封装到原生组件中。RCTRootView是一个UIView容器,承载着React Native应用。同时它也提供了一个联通原生端和被托管端的接口。
通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用。参数initialProperties必须是NSDictionary的一个实例。这一字典参数会在内部被转化为一个可供JS组件调用的JSON对象。
NSArray *imageList = @[@"http://foo.com/bar1.png",
@"http://foo.com/bar2.png"];
NSDictionary *props = @{@"images" : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"ImageBrowserApp"
initialProperties:props];
RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和之前的属性有区别时更新才会被触发。
从React Native传递属性到原生组件
属性的限制
跨语言属性的主要缺点是不支持回调方法,因而无法实现自下而上的数据绑定。设想你有一个小的RN视图,当一个JS动作触发时你想从原生的父视图中移除它。此时你会发现根本做不到,因为信息需要自下而上进行传递。
虽然我们有跨语言回调(参阅这里),但是这些回调函数并不总能满足需求。最主要的问题是它们并不是被设计来当作属性进行传递。这一机制的本意是允许我们从JS触发一个原生动作,然后用JS处理那个动作的处理结果。
其他的跨语言交互(事件和原生模块)
如上一章所说,使用属性总会有一些限制。有时候属性并不足以满足应用逻辑,因此我们需要更灵活的解决办法。这一章描述了其他的在React Native中可用的通信方法。他们可以用来内部通信(在JS和RN的原生层之间),也可以用作外部通信(在RN和纯原生部分之间)。
React Native允许使用跨语言的函数调用。你可以在JS中调用原生代码,也可以在原生代码中调用JS。在不同端需要用不同的方法来实现相同的目的。在原生代码中我们使用事件机制来调度JS中的处理函数,而在React Native中我们直接使用原生模块导出的方法。
从原生代码调用React Natvie函数(事件)
事件的详细用法在这篇文章中进行了讨论。注意使用事件无法确保执行的时间,因为事件的处理函数是在单独的线程中执行。
事件很强大,它可以不需要引用直接修改React Native组件。但是,当你使用时要注意下面这些陷阱:
由于事件可以从各种地方产生,它们可能导致混乱的依赖。
事件共享相同的命名空间,因此你可能遇到名字冲突。冲突不会在编写代码时被探测到,因此很难排错。
如果你使用了同一个React Native组件的多个引用,然后想在事件中区分它们,name你很可能需要在事件中同时传递一些标识(你可以使用原生视图中的reactTag作为标识)。
在React Native中嵌入原生组件时,通常的做法是用原生组件的RCTViewManager作为视图的代理,通过bridge向JS发送事件。这样可以集中在一处调用相关的事件。
从React Native中调用原生方法(原生模块)
原生模块是JS中也可以使用的Objective-C类。一般来说这样的每一个模块的实例都是在每一次通过JS bridge通信时创建的。他们可以导出任意的函数和常量给React Native。相关细节可以参阅这篇文章。
事实上原生模块的单实例模式限制了嵌入。假设我们有一个React Native组件被嵌入了一个原生视图,并且我们希望更新原生的父视图。使用原生模块机制,我们可以导出一个函数,不仅要接收预设参数,还要接收父视图的标识。这个标识将会用来获得父视图的引用以更新父视图。那样的话,我们需要维持模块中标识到原生模块的映射。 虽然这个解决办法很复杂,它仍被用在了管理所有React Native视图的RCTUIManager类中,