封裝IOS原生元件——匯出元件事件到RN端使用
阿新 • • 發佈:2020-08-05
匯出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', } });