I want to create a simple UIView subclass and then make it available as a React Native JavaScript component via bridging to React Native. I have followed these directions and thumbed through lots of the react source code: https://facebook.github.io/react-native/docs/native-components-ios.html
Unfortunately, I don't know where my React Native component is failing. This is my Obj-C manager class:
// header
#import "RCTViewManager.h"
#import "ColorPicker.h"
@interface ColorPickerManager : RCTViewManager
@end
// implementation
#import "ColorPickerManager.h"
@interface ColorPickerManager()
@property (nonatomic) ColorPicker * colorPicker;
@end
@implementation ColorPickerManager
RCT_EXPORT_MODULE()
- (instancetype)init {
self = [super init];
if ( self ) {
NSLog(@"color picker manager init");
self.colorPicker = [[ColorPicker alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
}
return self;
}
- (UIView *)view {
NSLog(@"color picker manager -view method");
return self.colorPicker;
}
@end
Here is my simple UIView subclass that I vend via the above -view
method:
// header
#import <UIKit/UIKit.h>
@interface ColorPicker : UIView
@end
// implementation
#import "ColorPicker.h"
@interface ColorPicker()
@property (nonatomic) NSArray * colors;
@end
@implementation ColorPicker
- (instancetype)init {
NSLog(@"init");
self = [super init];
if ( self ) {
[self setUp];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
NSLog(@"init with frame: %@", NSStringFromCGRect(frame));
self = [super initWithFrame:frame];
if ( self ) {
[self setUp];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
NSLog(@"init with coder: %@", aDecoder);
self = [super initWithCoder:aDecoder];
if ( self ) {
[self setUp];
}
return self;
}
- (void)setUp {
self.colors = @[[UIColor redColor], [UIColor greenColor], [UIColor blueColor]];
self.backgroundColor = self.colors[0];
}
- (void)layoutSubviews {
NSLog(@"layout subviews");
}
@end
Finally, here's my react component being bridged over to JavaScript:
var { requireNativeComponent } = require('react-native');
var ColorPicker = requireNativeComponent('ColorPicker', null);
module.exports = ColorPicker;
debugger;
And it's declaration and render to the screen:
'use strict';
var React = require('react-native');
var ColorPicker = require('./BridgedComponents/ColorPicker.js');
var {
StyleSheet
} = React;
var iOS = React.createClass({
render: function() {
debugger;
return (
<ColorPicker style={styles.container} />
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
AppRegistry.registerComponent('iOS', () => iOS);
This results in nothing rendering to the screen when I expect to see a 100x100 red square. What I have tried:
- I've added some border color and width to the ColorPicker to ensure that it is rendering something. It has a zero height/width, but I specify a 100x100 sized frame when I create the view.
- I've verified that my
UIView
will render exactly what I expect if I remove all React Native code from the project and by putting this view as a subview of a differentrootViewController
. - I have stepped through the debugger in both Xcode and Chrome to verify that the component's manager class initializes and vends the view. (This happens twice, by the way, probably because of reloading, but that still seems inefficient).
- I have stepped through all the bridging code as well to ensure that my module has been registered and vends its view to the list of bridged modules.
- I have verified that
ColorPicker
in my main .js file is notundefined
at the time its rendered to screen and when its created viadebugger
. - I have tried applying a style of
height: 100, width: 100
to the renderedColorPicker
but it still doesn't show a red squARE
Questions for RN Gurus - What else can I do to verify that my view is correctly bridged? - Is there anything I should look for in the Chrome Debugger when inspecting these instances to verify that the view was set up correctly? - I've tried following some of the source code in the repo but I'm still new to React and I'm not 100% how its all working. - When I create a bridged component am I expected to set the appearance and layout in the Obj-C/Swift class or is it better to do that in JavaScript with CSS. Seems to me the former would be expected.
Any help/advice will be greatly appreciated.