React-Native 调用iOS原生组件

今天我们来研究下RN如何去调用iOS的原生组件:

OC版

主要步骤
1、创建一个CropperMapViewBridge.m桥接文件
2、在CropperMapViewBridge里面创建一个RCTViewManager的子类,来管理原生组件
3、创建原生组件
4、在RN中调用原生组件

  • 创建RCTViewManager的子类文件
#import <React/RCTBridgeModule.h>
#import <React/RCTViewManager.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "CropperVieww.h"


@interface CropperMapViewManager: RCTViewManager
@end
 
@implementation CropperMapViewManager
 
// 将模块暴露给React端
RCT_EXPORT_MODULE()
// 设置属性 属性mapData 是从 RN 传来的参数
RCT_EXPORT_VIEW_PROPERTY(mapData,NSString)

// 设置回调方法 此回调方法主要是从原生回调去操作RN 的方法
// 注: 方法名前面一定要加上on  否则不会被执行
RCT_EXPORT_VIEW_PROPERTY(onFindMachineLocation, RCTBubblingEventBlock)

-(UIView *)view {
    
    return [[CropperView alloc] initWithFrame: CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width - 24, UIScreen.mainScreen.bounds.size.width - 24)];
    
}

@end

  • RCT_EXPORT_MODULE() 是必须要写的
  • -(UIView *)view里面调用我们需要的UI组件,里面的frame 可以不写,因为会被RN里面设置的覆盖
  • 创建原生UI组件
#import <UIKit/UIKit.h>
#import "React/RCTComponent.h"
@interface CropperView : UIView
// RN 组件传来的属性
@property(nonatomic, copy) NSString *mapData;
// 回调方法
@property(nonatomic, copy) RCTBubblingEventBlock onFaceDetection;
@end

#import "CropperView.h"
@implementation CropperView


- (instancetype)init
{
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor redColor];
        [self setUI];
    }
    return self;
}

- (void)setUI {
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 40, 50)];
    button.backgroundColor = [UIColor grayColor];
    [button addTarget:self action:@selector((find:)) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:button];
}

- (void)find:(UIButton*)button {
	// 回调函数 可传参
    self.onFaceDetection(@{@"key": @"laoma"});
}

// 重写属性
// RN 部分的属性被赋值后会自动调用这个方法传参
- (void)setMapData:(NSString *)mapData {
    NSLog(mapData);
}
@end
  • 创建RN文件
import React ,{Component} from 'react'
import { requireNativeComponent } from 'react-native'
import PropTypes from 'prop-types';

var RECTMapView  = requireNativeComponent('CropperMapView',CustomMapView, {nativeOnly: {}});

class CustomMapView extends Component{

    static propTypes = {
        // 属性 传给原生组件的参数 被赋值后悔自动调用原生的`mapData`的setter 方法
        mapData: PropTypes.string,
      };

    constructor(props) {
        super(props);
        console.log(this.props.mapData)
        
    }   
    
    // 查找设备位置
    _findMachineLocation = (event) => {
        console.log('');
        console.log('_findMachineLocation');
        console.log(event.nativeEvent);

    };

    render(){
        return(
            <RECTMapView {...this.props}
            onFindMachineLocation={this._findMachineLocation}
            />
        );
    }

}

module.exports = CustomMapView

在这里插入图片描述

  • 12为直接导出的组件名称,这俩名称必须一致
  • 3 为原生组件的名称 CropperMapViewManager,调用的时候会自动补全后面的Manager。这个字段一定要和CropperMapViewManagerManager前面的名字保持一致。
  • 45RN模块的名称,这俩也得保持一致
  • mapData这个属性要和原生的View中的属性保持一致
  • onFindMachineLocation这个回调方法名称也的和原生的保持一致
Swift版本

核心步骤跟OC版的一样,不同的是CropperMapViewManager里面调用CropperView的方法不一样,UI组件的设置参数和回调方法不一样。

  • CropperMapViewManager
#import <React/RCTBridgeModule.h>
#import <React/RCTViewManager.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
// Swift 和 OC 混编需要这样调用swift文件
#import <TBCropperMapModule/TBCropperMapModule-Swift.h>


@interface CropperMapView: RCTViewManager
@end
 
@implementation CropperMapView
 
// 将模块暴露给React端
RCT_EXPORT_MODULE()
// 设置属性 属性mapData 是从 RN 传来的参数
RCT_EXPORT_VIEW_PROPERTY(mapData,NSString)

// 设置回调方法 此回调方法主要是从原生回调去操作RN 的方法
RCT_EXPORT_VIEW_PROPERTY(onFindMachineLocation, RCTBubblingEventBlock)

-(UIView *)view {
    
    return [[CropperView alloc] initWithFrame: CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width - 24, UIScreen.mainScreen.bounds.size.width - 24)];
    
}
 
@end

  • #import <TBCropperMapModule/TBCropperMapModule-Swift.h>
    因为我是用的组件模块开发,所以这样调用。通常情况下OC调用Swift文件,直接#imp
  • UI组件
import UIKit
import SnapKit
import React
public class CropperView: UIView {
    

    private var mapView:BitMapView = BitMapView(frame: CGRect(x: 0, y: 0, width: 78, height: 76))
    // RN 传过来的参数 
    @objc
    var mapData: String = "" {
        didSet {
            print(mapData)
            self.updateMapView()
        }
    }
    // 回调函数
    @objc
    var onFindMachineLocation: RCTBubblingEventBlock?
    
    func setMapData(mapData: String) {
        print(mapData)
    }
    
    override public init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = .green
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
   
    @objc
    func findMachine() {
        self.onFindMachineLocation!(["key":"laomma"])
    }
    
    private func setMapView() {
        let mapView = UIView()
        mapView.frame = CGRect(x: 10, y: 10, width: 10, height: 10)
        mapView.backgroundColor = .red
        self.addSubview(mapView)
    }
    
}

注: 属性mapData和回调参数self.onFindMachineLocation都需要加上@objc修饰,不然不起作用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值