1. 程式人生 > 實用技巧 >封裝IOS原生元件——匯出元件事件到RN端使用

封裝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,
                        width: 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、執行效果