分享React Native与原生模块交互之iOS篇

发布于25天前 作者shen100 174次浏览

为什么需要使用原生模块?

有时候App需要访问平台API,但React Native可能还没有相应的模块封装;或者你需要复用Objective-C、Swift或C++代码,而不是用JavaScript重新实现一遍;又或者你需要实现某些高性能、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。

JavaScript与Objective-C交互

Objective-C代码

MyNativeModule.h

#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

// 在React Native中,如果实现一个原生模块
// 需要实现"RCTBridgeModule"协议,其中RCT就是ReaCT的缩写
@interface MyNativeModule : RCTEventEmitter <RCTBridgeModule>

@end

MyNativeModule.m

#import "MyNativeModule.h"

@implementation MyNativeModule

// 这个宏可以添加一个参数用来指定在JavaScript中访问这个模块的名字
// 如果不指定,默认就会使用这个Objective-C类的名字
RCT_EXPORT_MODULE();

// RCT_EXPORT_METHOD()宏来实现要给JavaScript导出的方法
RCT_EXPORT_METHOD(sayHello:(NSString *)name event:(RCTResponseSenderBlock)callback)
{
    NSString *result = [NSString stringWithFormat:@"%@, %@", @"Hello", name];
    // 通过回调函数给JavaScript返回结果
    // 第一个参数是错误对象,第二个参数是数组
    callback(@[[NSNull null], result]);
  
    [self onStart:[NSString stringWithFormat:@"%@, %@", name, @"data1 from onStart"]];
    [self onEnd:[NSString stringWithFormat:@"%@, %@", name, @"data2 from onEnd"]];
}

- (NSArray<NSString *> *)supportedEvents
{
    return @[@"onStart", @"onEnd"];
}

- (void)onStart:(NSString *)msg
{
    // Objective-C也可以直接给JavaScript发送事件
    [self sendEventWithName:@"onStart" body:msg];
}

- (void)onEnd:(NSString *)msg
{
    // Objective-C也可以直接给JavaScript发送事件
    [self sendEventWithName:@"onEnd" body:msg];
}

@end

JavaScript代码

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    NativeModules,
    NativeEventEmitter
} from 'react-native';

export default class golang123ReactNative extends Component {
    constructor() {
        super();
        this.onNativeEvent = this.onNativeEvent.bind(this);
        this.state = {
            helloMsg: '',
            eventMsg: ''
        };
    }
    componentDidMount() {
        let MyNativeModule = NativeModules.MyNativeModule;

         //创建自定义事件接口  
        let myNativeEvt = new NativeEventEmitter(MyNativeModule);
        //对应了原生端的事件名称
        this.listener = myNativeEvt.addListener('onStart', this.onNativeEvent); 
        this.listener = myNativeEvt.addListener('onEnd', this.onNativeEvent);
        // 调用原生端的方法sayHello,传字符串参数"golang123"
        MyNativeModule.sayHello("golang123", (err, result) => {
            if (!err) {
                this.setState({
                    helloMsg: result
                });
            }
        });
    }

    componentWillUnmount() {  
        this.listener && this.listener.remove();
        this.listener = null;  
    }  

    onNativeEvent(msg) {
        this.setState({
            eventMsg: this.state.eventMsg + '\n'+ msg
        });    
    } 

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.text}>{this.state.helloMsg}</Text>
                <Text style={styles.text}>{this.state.eventMsg}</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    text: {
        fontSize: 20,
        paddingBottom: 12,
        textAlign: 'center',
        margin: 10
    }
});

AppRegistry.registerComponent('golang123ReactNative', () => golang123ReactNative);
收藏
分享
暂无回复