封装IOS原生组件——导出组件事件到RN端使用

导出IOS原生组件的事件到RN端的步骤。

1、在IOS组件的头文件声明一个事件属性。

2、在RN组件桥接类里面导出这个事件属性。

3、在IOS原生端通过定义的事件属性发送事件到RN端。

4、在RN端封装IOS原生组件事件。

1、在IOS组件的头文件声明一个事件属性

TestReactNativeView.h

//
//  TestReactNativeView.h
//  NativeCommunicationDemo
//
//  Created by chenlw on 2019/4/10.
//  Copyright © 2019 Facebook. All rights reserved.
//
 
#import <UIKit/UIKit.h>
#import "React/RCTComponent.h"
 
NS_ASSUME_NONNULL_BEGIN
 
@interface TestReactNativeView : UIView
// type操作类型
@property(nonatomic,weak) NSString * type;
 
//如果使用assign会导致线程锁死,使用weak弱引用就没有问题
//@property(nonatomic,assign) UITextView *textView;
@property(nonatomic,weak) UITextView *textView;
 
// 声明一个事件属性,导出给RN端使用
@property(nonatomic, copy) RCTBubblingEventBlock onFaceDetection;
 
@end
 
NS_ASSUME_NONNULL_END

2、在RN组件桥接类导出这个事件属性

TestReactNativeViewManager.m

//
//  TestReactNativeViewManager.m
//  NativeCommunicationDemo
//
//  Created by chenlw on 2019/4/10.
//  Copyright © 2019 Facebook. All rights reserved.
//
 
#import "TestReactNativeViewManager.h"
#import "TestReactNativeView.h"
 
@implementation TestReactNativeViewManager
 
 
//导出桥接宏标记
RCT_EXPORT_MODULE()
 
//导出RN组件的属性
RCT_EXPORT_VIEW_PROPERTY(type, NSString)
 
//导出RN组件的事件
RCT_EXPORT_VIEW_PROPERTY(onFaceDetection, RCTBubblingEventBlock)
 
- (UIView *)view
{
    //创建组件实例
    TestReactNativeView * viewInstance =[[TestReactNativeView alloc] init];
    return viewInstance;
}
 
@end

3、在IOS原生端通过定义的事件属性发送事件到RN端

模拟场景:在IOS原生自定义组件上添加一个按钮,点击按钮的时候,往RN发送事件。

这里,我们通过一个按钮的点击事件来发送事件到RN端。

TestReactNativeView.m

//
//  TestReactNativeView.m
//  NativeCommunicationDemo
//
//  Created by chenlw on 2019/4/10.
//  Copyright © 2019 Facebook. All rights reserved.
//
 
#import "TestReactNativeView.h"
 
//ReactNative封装IOS原生组件,这里编写一个测试用的组件类
@implementation TestReactNativeView
 
/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect {
 // Drawing code
 }
 */
 
- (instancetype)init
{
    //初始化组件
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor redColor];
    }
    
    //创建一个文本组件
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20,20,300,40)];
    //设置文字
    textView.text = @"IOS原生组件";
    //设置字体大小
    [textView setFont:[UIFont systemFontOfSize:20]];
    //添加文件组件
    [self addSubview:textView];
    
    self.textView = textView;
    
    //创建一个按钮组件
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    button.frame = CGRectMake(20, 80, 100, 40);
    [button setTitle:@"发送事件到RN" forState:UIControlStateNormal];
//    [button addTarget:self action:@selector(sendEventToReactNative) forControlEvents:UIViewNoIntrinsicMetric];
    /**
     * addTarget:目标(让谁做这个事情)
     * action:方法(做什么事情-->方法)
     * forControlEvents:事件
     */
    [button addTarget:self action:@selector(sendEventToReactNative:) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:button];
    //[self bringSubviewToFront:button];
    
    return self;
}
 
//重写设置属性方法,当RN端设置type属性,就会调用这个方法
-(void)setType:(NSString *)type{
    NSLog(@"setType");
    self.textView.text = type;
    //self.type = type;
}
 
//按钮的响应事件
- (void)sendEventToReactNative:(UIButton *)button{
    NSLog(@"sendEventToReactNative");
    //往RN端发送事件
    self.onFaceDetection(@{@"faceBase64":@"IOS原生端回传的数据"});
}
 
 
@end

4、在RN端封装IOS原生组件事件

在RN组件内部,对这个事件进行封装处理,过滤掉对RN端无用的参数。

'use strict';
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
    requireNativeComponent,
    View,
} from 'react-native';
 
const TestReactNativeView = requireNativeComponent('TestReactNativeView', TestReactNativeViewComponent
    , {nativeOnly: {}});
 
//对封装的组件进行二次封装
class TestReactNativeViewComponent extends Component {
 
    constructor(props) {
        super(props);
    }
 
    /**
     * 对IOS组件的事件进行处理,解析对RN端有用的参数
     * @param event
     * @private
     */
    _onFaceDetection = (event) => {
        if (!this.props.onFaceDetection) {
            return;
        }
        console.log('');
        console.log('_onFaceDetection');
        console.log(event.nativeEvent);
        this.props.onFaceDetection(event.nativeEvent.faceBase64);
    };
 
    render() {
        return (
            <TestReactNativeView
                {...this.props}
                onFaceDetection={this._onFaceDetection}
            />
        );
    }
}
 
TestReactNativeViewComponent.propTypes = {
    type: PropTypes.string,
    onFaceDetection: PropTypes.func,
    ...View.propTypes,
};
 
//导出二次封装的组件
module.exports = TestReactNativeViewComponent;

5、测试页面

import React, {Component} from 'react';
import {Dimensions, StyleSheet, View} from 'react-native';
import TestReactNativeView from './TestReactNativeView';
 
const screenWidth = Dimensions.get('window').width;
 
/**
 * IOS原生组件封装,注意RN端设置组件的宽度和高度,这样组件才能显示。
 */
export default class TestReactNativeViewExample extends Component {
 
    static navigationOptions = {
        headerTitle: 'IOS原生组件封装example',
    };
 
    constructor(props, context) {
        super(props, context);
    }
 
 
    render() {
 
        return (
            <View style={styles.container}>
                <TestReactNativeView
                    style={{
                        flex: 1,
                         screenWidth,
                    }}
                    type={'type from react-native'}
                    onFaceDetection={(faceBase64) => {
                        console.log('');
                        console.log('TestReactNativeViewExample.TestReactNativeView');
                        console.log(faceBase64);
                        alert('RN端接收到IOS原生端发送的事件:'+faceBase64);
                    }}
                />
            </View>
        )
    }
 
 
}
 
const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    }
});

6、运行效果

原文地址:https://www.cnblogs.com/itgezhu/p/13439616.html