9) React Native package native UI component (iOS)

The communication between React and Native on the original article (iOS), we know that RN and primary properties, mainly through the communication module, the primary package native UI components in three ways, the article is mainly about the above two ways, this article on the three ways.
React Native as an entry-level, limited knowledge, see the official document (face Meng b), find a lot of blogs, source code to study how to encapsulate the iOS end of the primary control results and try a few days still can only have a simple package of native UI, so JS can call its attributes and events (not complete), so this article is not complete, I hope RN master can give some advice or blog guidance, and discuss the local welcome message written in the wrong…

9) React Native package native UI component (iOS)
JS and native.png

Native development, development has been very mature and perfect today, there are thousands of components, greatly improving the efficiency of development. The React Native on React.js conf 2015 proposed, so far more than a year, the number of components must not be compared to the original and the Facebook.
so, in the process of using React Native to develop App, we may need to call the RN does not implement the native view component or third party components. Even, we can build the local module into a React Native component that is available to others.

In this paper, demo based on SDCycleScrollView, that is, banner, because of the unexpected good example, so do the project used in the SDCycleScrollView package, directly to the JS call.

SDCycleScrollView is an infinite loop automatic picture carousel GitHub open source.
address: https://github.com/gsdios/SDCycleScrollView
will use SDWebImage, if the project has been used in SDWebImage, is recommended directly to the SDCycleScrollView code into the OK project.

First, the native view for further packaging

Reference to other people on the original view of the package, most of them will create a new view, inheritance (or sub view contains) native view, which may contain the event call (here is a simple demo, not used).
#import “UIView+React.h”, the extension of the native view (here is an important attribute of reactTag, will be used later, as a separate purpose).


#import "SDCycleScrollView.h" #import "RCTComponent.h" #import "UIView+React.h" TestScrollView @interface: SDCycleScrollView @property (nonatomic, copy) RCTBubblingEventBlock onClickBanner; @end

The block property of the RCTBubblingEventBlock or RCTBubblingEventBlock type declared in the encapsulated UIView can be exported as an event. (new event export mode, which will be used later)
note: declare the block property name to start with on (not sure why, in the absence of other configurations, only the beginning of on can be successful)


The third component of the #import "TestScrollView.h" @implementation TestScrollView / * * * a lot of package native will write this, here is not studied thoroughly, not as to achieve - (instancetype) initWithBridge: (RCTBridge *) bridge ({if (self = [super initWithFrame:CGRectZero])) {_eventDispatcher = bridge.eventDispatcher; _bridge = bridge;...... return self @end * /}};

Two. Create a RCTViewManager subclass to create and manage native views

Native views need to be created and managed by a RCTViewManager subclass.
these managers are functionally similar to the view controller, but they are essentially single – React Native creates an instance for each manager.
they create native views and provide them with RCTUIManager, which in turn will delegate RCTUIManager to set and update the properties of the view when needed. RCTViewManager also delegates all delegates to the view and sends back the corresponding events to JavaScript.

Provide native view steps as follows:

  • First create a subclass named naming convention “view name +Manager”. The view name can be prefixed with its own prefix, so it’s best to avoid using the RCT prefix, unless you want to give the official pull request
  • Add RCT_EXPORT_MODULE () tag macro – expose module interface to JavaScript
  • Implementation – (UIView *) view method – create and return component view
  • Package properties and delivery events

The following is the first to paste the complete code, and then the properties and events for further explanation.


#import "RCTViewManager.h" @interface TestScrollViewManager: RCTViewManager @end


#import "TestScrollViewManager.h" #import "TestScrollView.h" / / the third party component header file #import "RCTBridge.h" / / communication #import file "RCTEventDispatcher.h" / / event dispatch, not import will cause Xcode TestScrollViewManager @interface (<) warning; SDCycleScrollViewDelegate> @end; @implementation TestScrollViewManager / / mark (necessary) RCT_EXPORT_MODULE (macro) / events are derived. Attribute RCT_EXPORT_VIEW_PROPERTY extended onClickBanner corresponds to view (onClickBanner, RCTBubblingEventBlock) / / RCT_EXPORT_VIEW_PROPERTY mapped and derived by the macro properties of RCT_EXPORT_VIEW_PROPERTY (autoScrollTimeInterval, CGFloat); RCT_EXPORT_VIEW_PROPERTY (imageURLStringsGroup, NSArray; RCT_EXPORT_VIEW_PROPERTY (autoScroll), BOOL); - (UIView *) specific size and position view {/ / actual component controlled by JS TestScrollView *testScrollView [TestScrollView cycleScrollViewWithFrame:CGRectZero delegate:self = placeholderImage:nil]; / / initialize delegate will point to self testScrollView.pageControlStyle = SDCycleScrollViewPageContolStyleClassic; testScrollView.pageControlAliment = SDCycleScrollViewPageContolAlimentCenter; return testScrollView;} / * * * when events lead to use sendInputEventWithName mode, will be used to (NSArray * customDirectEventTypes) @[@ {return "onClickBanner"]; #pragma mark SDCycleScrollViewDelegate * /} / * * * * click on Banner - (void) cycleScrollView: (TestScrollView * cycleScrollView didSelectItemAtIndex: (NSInteg) Er index) {/ / this is derived from the incident, but like the old method, there will be a warning to sendInputEventWithName:@ "onClickBanner" / / [self.bridge.eventDispatcher / / body:@{@ / / cycleScrollView.reactTag: "target", "value": [NSNumber @ numberWithInteger:index+1] /}]; if (! CycleScrollView.onClickBanner) {return}; NSLog ("OC did click%li @" [cycleScrollView.reactTag, integerValue]); / / cycleScrollView.onClickBanner (@{@ derived events: cycleScrollView.reactTag "target", "value": [NSNumber @ numberWithInteger:index+1 ]});} / / derived enum constants for JS style - (NSDictionary *) constantsToExport return @{@ {"SDCycleScrollViewPageContolAliment": "right": @{@ @ @ (SDCycleScrollViewPageContolAlimentRight), "center": @ (SDCycleScrollViewPageContolAlimentCenter)}};} / / because this class inherits from RCTViewManager, RCTBridgeModule, so you can the use of native modules all characteristics of this method do not use RCT_EXPORT_METHOD / (testResetTime: (RCTResponseSenderBlock) {callback (callback) @[@ (234)]);} @end


RCT_EXPORT_VIEW_PROPERTY (autoScrollTimeInterval, CGFloat);

Complete the mapping and export of attributes by macro RCT_EXPORT_VIEW_PROPERTY.
CGFloat for autoScrollTimeInterval OC data types, converted into JS corresponding to number.

React Native uses RCTConvert to complete the conversion between JavaScript and native code. The default conversion type (part) supported by
is as follows:

  • String (NSString)
  • Number (NSInteger, float, double, CGFloat, NSNumber)
  • Boolean (BOOL, NSNumber)
  • Array (NSArray) contains any type in this list
  • Map (NSDictionary) contains keys of type string and any type of value in this list

If the conversion is not complete, it will produce a “red screen” error warning prompt, so you can immediately know that there is a problem in the code. If all goes well, the macro above already contains the full implementation of the derived property.

PS: more complex type conversion, it relates to the type of MKCoordinateRegion, this article did not do the application, the specific reference to the official document example.


There is an interaction between the JS and the native, for example, in the native implementation of the proxy or click event, JS also need to get real-time access to such events, you need to use the event to interact. There are two ways to realize the

  1. By sendInputEventWithName
    customDirectEventTypes, 1) returns an array of custom name (at the beginning of the on is valid) – (NSArray * customDirectEventTypes) {return}] @[@ “onClickBanner”; 2) sendInputEventWithName event calls (reactTag for example to distinguish [self.bridge.eventDispatcher sendInputEventWithName:@) “onClickBanner” body:@{@ “target” cycleScrollView.reactTag, “@ value: [NSNumber numberWithInteger:index+1]}];
  2. Through RCTBubblingEventBlock
    1) add the block attribute RCTBubblingEventBlock in package View (at the beginning of the on is valid) @property (nonatomic, copy) RCTBubblingEventBlock onClickBanner; 2) in the Manager class by Acer RCT_EXPORT_VIEW_PROPERTY completed mapping and export RCT_EXPORT_VIEW_PROPERTY Block properties (onClickBanner, RCTBubblingEventBlock) 3 (reactTag) to implement event call for instance distinction (cycleScrollView.onClickBanner) @{@: cycleScrollView.reactTag “target”, “value”: [NSNumber @ numberWithInteger:index+1]});

Through the above two ways to package a good event in the JS can be directly used by the same function call can be (shown later).
but the incident on this piece, quite a few do not fully understand, I hope there is great God to guide, for example, why can only define the beginning of the on, how to customize, how to reply to the event data source, etc….


Because all of our views are subclasses of UIView, most of the style attributes should be valid. Some attribute definitions, the need to use enumeration, you can take advantage of the way to pass through the native to achieve a constant, as follows:

/ / derived enum constants for JS style - (NSDictionary *) constantsToExport return @{@ {"SDCycleScrollViewPageContolAliment": "right": @{@ @ @ (SDCycleScrollViewPageContolAlimentRight), "center": @ (SDCycleScrollViewPageContolAlimentCenter)}}};

Call in JS is as follows:

/ / the first access to the constant var TestScrollViewConsts = require ('react-native').UIManager.TestScrollView.Constants < TestScrollView style={styles.container}; / / call; pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right} />

Ps: part of the component will want to use their own definition of the default style, such as UIDatePicker want their size is fixed. For example, the size of the default size of the native, this example can refer to the specific style of the official document module.

Three, in the JS call

In the JS call, there are two ways, one for the direct extension of the React component as a call, two for a new component package, and then call.
below in second ways, the official recommendation, the logic is clear.

1 first into the original component, the new TestScrollView.js file, in which the TestScrollView import, the type of attribute declarations, etc.. Specific code and explanations are as follows:


Import / / TestScrollView.js React PropTypes from'react'{Component}, {requireNativeComponent}; import from'react-native'; / / requireNativeComponent automatically the assembly is provided to the "RCTScrollView" var RCTScrollView = requireNativeComponent ('TestScrollView', TestScrollView); export default class TestScrollView extends Component (return) {render {< this.props}; /> RCTScrollView {...}} TestScrollView.propTypes = {/ * * * property type, actually does not write can, JS will automatically convert type / autoScrollTimeInterval: PropTypes.number, imageURLStringsGroup: PropTypes.array, autoScroll: PropTypes.bool, onClickBanner: PropTypes.func}; module.exports = TestScrollView;

2 call in index.ios.js


Var TestScrollView = require ('./TestScrollView'); / / requireNativeComponent automatically the assembly is provided to the "TestScrollView" / / if not new TestScrollView.js on the primary package statement, this sentence can be imported directly by TestScrollView / / var = requireNativeComponent ('TestScrollView', null); / / TestScrollViewConsts = require into constant var ('react-native').UIManager.TestScrollView.Constants; VAR = [bannerImgs'http://upload-images.jianshu.io/upload_images/ 2321678-ba5bf97ec3462662.png? ImageMogr2/auto-orient/strip%7CimageView2/2','http://upload-images.jianshu.io/upload_images/1487291-2aec9e634117c24b.jpeg imageMogr2/auto-orient/strip%7CimageView2/2/w/480/q/100','http://f.hiphotos.baidu.com/zhidao/ pic/item/e7cd7b899e510fb37a4f2df3? Db33c895d1430c7b.jpg'class NativeUIModule extends Component]; {constructor (props) {super (props); this.state={bannerNum:0 (render) {return}} (< ScrollView; style = {{marginTop:64}}> < View> < TestScrollView style={styles.container} autoScrollTimeInterval = {2} imageURLStringsGroup = {bannerImgs} pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right} onClickBanner={(E =>) {console.log ('test' + e.nativeEvent.value;); this.setState ({bannerNum:e.nativeEvent.value});}} /> < Text style={{fontSize: 15, margin: 10, textAlign:'center'}}> Click on the banner -> {this.state.bannerNum} < /Text> < /View> < /ScrollView>}}); the specific size and position / actual component controlled by JS const StyleSheet.create (styles = {container:{padding:30, borderColor:'#e7e7e7', marginTop:10, height:200},}); AppRegistry.registerComponent ('NativeTest2') (=> NativeUIModule);

If you use the first method, use the following statement to refer to the component:

Var TestScrollView = requireNativeComponent ('TestScrollView', null);

Such problems will exist:
although very simple, but this is not a good description of the component usage, users want to know what are the attributes of our components can be used, and can take what kind of value, the way he had to turn to the Objective-C code. To solve this problem, we can create a package component, and through PropTypes to illustrate the interface of the component.

Note: we are now turning the second parameters of the requireNativeComponent from the null to the encapsulated component TestScrollView. This allows the underlying framework of the React Native to check whether the properties of the native and wrapper classes are consistent to reduce the likelihood of problems.

On attributes, events, the call is as follows:

< TestScrollView style={styles.container} autoScrollTimeInterval = {2} imageURLStringsGroup = {bannerImgs} pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right} onClickBanner={(E) => {console.log ('test'+ e.nativeEvent.value); this.setState ({bannerNum:e.nativeEvent.value});}} />

On the event, it should be noted that the event event is passed by default dictionary data types, that is, JSON, in the JS call the need to use e.nativeEvent to extract the dictionary, the value of the specific call inside. (it’s not a thorough study yet, need guidance)

Four, results

So far, should be able to package and call for simple native UI controls, if not to the data source, only the third party agent to achieve control, packaging to make RN module is useless +_+ related articles recommend the following questions useful:
1 official document – native UI components (this yes
2.React Native) to construct the local view component of
3.React-Native UI
4.React Native multiplexing native components – How to Bridge an Objective-C View Component and the third party package code for the native tableview
https://github.com/aksonov/react-native-tableview: in addition, the interaction principle on the following recommendation:
[iOS] React Native | | speed of dry cargo iOS source code analysis report (two) wpap6 03001br analysis of the communication mechanism of ReactNative (bang’s)
blog: React Native communication mechanism

Demo or temporarily put in the Baidu cloud:


The following is a demonstration of the effect of demo:

9) React Native package native UI component (iOS)
native UI component test.gif

A iOS package native UI component tutorial on here, there are many written deficiencies in the hope that people really understand to give advice, continue to get RN, so there may be updated later, now do not know where to fill the shortage…

React is writing a tutorial to learn Native ing, the results are as follows: 1)
React Native and
2) React Native entry environment to build and create a project (Mac)
3) React Native IDE
4) React development of the Native into the door project and analysis of
5 React Native JS) and React based
6) React Native component life cycle (ES6)
7) React Native integrated into the original project (iOS)
8) communication between React Native and native
(iOS) 9) React Native UI (iOS) package of primary components