为啥我的 React Native 桥接 iOS 组件不起作用?

Posted

技术标签:

【中文标题】为啥我的 React Native 桥接 iOS 组件不起作用?【英文标题】:Why does my React Native bridged iOS component not work?为什么我的 React Native 桥接 iOS 组件不起作用? 【发布时间】:2015-12-15 17:00:13 【问题描述】:

我想创建一个简单的 UIView 子类,然后通过桥接到 React Native 使其可用作 React Native javascript 组件。我遵循了这些指示,并浏览了许多 React 源代码:https://facebook.github.io/react-native/docs/native-components-ios.html

不幸的是,我不知道我的 React Native 组件哪里出了问题。这是我的 Obj-C 管理器类:

// 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;

@结束

这是我通过上述-view 方法出售的简单 UIView 子类:

// 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

最后,这是我的 react 组件被桥接到 JavaScript:

var  requireNativeComponent  = require('react-native');
var ColorPicker = requireNativeComponent('ColorPicker', null);
module.exports = ColorPicker;
debugger;

它是声明并渲染到屏幕上:

'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);

当我希望看到 100x100 的红色方块时,这会导致屏幕上没有任何渲染。我尝试过的:

我已向 ColorPicker 添加了一些边框颜色和宽度,以确保它正在渲染某些内容。它的高度/宽度为零,但我在创建视图时指定了 100x100 大小的框架。 我已验证,如果我从项目中删除所有 React Native 代码并将此视图作为不同 rootViewController 的子视图,我的 UIView 将完全呈现我的预期。 我已经在 Xcode 和 Chrome 中逐步检查了调试器,以验证组件的管理器类是否已初始化并出售视图。 (顺便说一下,这发生了两次,可能是因为重新加载,但这似乎仍然效率低下)。 我还单步执行了所有桥接代码,以确保我的模块已注册并将其视图提供给桥接模块列表。 我已经验证我的主 .js 文件中的 ColorPicker 在它呈现到屏幕时以及通过 debugger 创建时不是 undefined。 我已尝试将 height: 100, width: 100 样式应用于渲染的 ColorPicker,但它仍然没有显示红色方块

给 RN 大师的问题 - 我还能做些什么来验证我的视图是否正确桥接? - 在检查这些实例以验证视图是否设置正确时,我应该在 Chrome 调试器中寻找什么吗? - 我已经尝试关注 repo 中的一些源代码,但我对 React 还是很陌生,而且我不是 100% 它是如何工作的。 - 当我创建一个桥接组件时,我希望在 Obj-C/Swift 类中设置外观和布局,还是在 JavaScript 和 CSS 中这样做更好。在我看来,前者是意料之中的。

任何帮助/建议将不胜感激。

【问题讨论】:

【参考方案1】:

除了添加了 ColorPicker 视图之外,您什么也看不到。

问题是 ReactNative 正在管理其 backgroundColor 属性本身并覆盖您最初的选择。

您可以在ColorPicker.m 中添加以下方法并设置断点以查看何时发生:

- (void)setBackgroundColor:(UIColor *)backgroundColor 
    NSLog(@"setBackgroundColor %@", backgroundColor);
    [super setBackgroundColor:backgroundColor];

您应该让 React Native 处理桥接组件的大小和外观。 但完全可以找到完全由本地控制的自定义子视图。

还有你的 ColorPickerManager should return a new instance 视图,当它调用 view 方法时,你正在桥接视图。

即你应该使用这个:

@implementation ColorPickerManager

RCT_EXPORT_MODULE()

- (instancetype)init 
  self = [super init];
  if ( self ) 
    NSLog(@"color picker manager init");
  
  return self;


- (UIView *)view 
  NSLog(@"color picker manager -view method");
  return [[ColorPicker alloc] init];


@end

否则,您将无法显示您的 ColorPicker 组件的 2 个(或更多)实例。

【讨论】:

关于setBackgroundColor: 方法的要点。但是如果我想设置自己的backgroundColorheightwidth 怎么办?我该怎么做?简单地桥接现有组件将需要您仔细检查当前组件是否尚未对这些属性执行特定操作。没有?

以上是关于为啥我的 React Native 桥接 iOS 组件不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的代码不能在 web 中的 react-native 代码中运行

为啥我不能运行我的 React Native 项目?

为啥我不能在 ios 设备上关闭并重新打开 react-native 调试?

为啥我们不在 react-native 中 gitignore ios/ 和 android/

为啥 React Native Picker 不会在 iOS 上显示?

为啥 React Native RNFS 的 copyFile() 无法访问 iOS 上的现有文件?