乐趣区

关于javascript:RN与IOS原生双向通信以及UI绑定通信的使用方式

react-native 提交给 IOS 客户端数据来实现通信或者交互有 2 种形式:

1、双向通信的形式:

RN to IOS

原生端:

#import <React/RCTBridgeModule.h>

@implementation RNToNativeEmitter

RCT_EXPORT_MODULE(RNToNativeEmitter);

RCT_EXPORT_METHOD(showText:(NSString *)textValue) textHeight:(CGFloat)height
{dispatch_async(dispatch_get_main_queue(), ^{
        // 在主线程种承受并解决数据
        ...
    });
}

RN 端:

import {NativeModules} from 'react-native';

//RNToNativeEmitter 为 OC 的类名称,showText 是 OC 宏注册的办法名称
NativeModules.RNToNativeEmitter.showText('显示的文本', 200);

IOS to RN

原生端:

NativeToRNEmitter.h:

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

@interface NativeToRNEmitter : RCTEventEmitter <RCTBridgeModule>

NativeToRNEmitter.m:

- (NSArray<NSString *> *)supportedEvents {return @[@"EmitterMsg"];// 注册的 RN 的办法名称
}

// 注册本地告诉来实现在其余模块中调用 sendEventWithName 的办法
-(void)beginObserving
{[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(emitEventInternal:)
                                                 name:@"EmitterMsg"
                                               object:nil];
}

-(void)endObserving
{[[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)emitEventInternal:(NSNotification *)notification
{
    [self sendEventWithName:@"EmitterMsg"
                       body:notification.userInfo];
}

OC 在须要的中央调用:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"EmitterMsg"
                                                        object:self
                                                      userInfo:@{}];

RN 接收端:

import {NativeEventEmitter} from 'react-native';
var messager = new NativeEventEmitter(NativeToRNEmitter);
messager.addListener("EmitterMsg", (result) => {//result 为上个代码快中 userInfo 参数的字典对象});

2、UI 绑定通信的形式

原生端:

首先创立一个继承于 UIView 的 CategoryView(举栗子)类,这个类有如下性能:
1、有一个成员办法 -(void)showCategoryName:(NSString*)textValue
2、外部渲染了一个 RCTView 的 RN 对象。

CategoryViewManager.h(类名为指标对象的 UIView 对象名称 +Manager)

#import <React/RCTViewManager.h>

@interface CategoryViewManager: RCTViewManager

CategoryViewManager.m

@interface CategoryViewManager()

@property (nonatomic, strong) CategoryView *cView;

@end

@implementation CategoryViewManager

RCT_EXPORT_MODULE()

// 创立指标 UIView 的实例
- (UIView *)view {self.cView = [[CategoryView alloc] initWithFrame:CGRectZero];
    return self.cView;
}

RCT_EXPORT_METHOD(showCategoryName:(nonnull NSNumber *)reactTag textValue:(nonnull NSString*)textValue) {[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {CategoryView *view = viewRegistry[reactTag];// 从注册的 CategoryView 汇合中获取实例
        if(view&&[view isKindOfClass:[CategoryView class]]){[view showCategoryName:textValue];
        }
    }];
}

@end

RN 端:

首先一个组件类用于映射到原生组件

import {requireNativeComponent, findNodeHandle, UIManager} from 'react-native';

const CategoryView = requireNativeComponent('CategoryView', Category);//CategoryView 与 IOS 端类名统一

class Category extends PureComponent {sendTextValue2Native(textValue) {
        //CategoryView 与 IOS 端类名统一,showCategoryName 办法名与 RCT_EXPORT_METHOD 注册的办法名称保持一致
        UIManager.dispatchViewManagerCommand(findNodeHandle(this),
            UIManager.getViewManagerConfig('CategoryView').Commands.showCategoryName,
            [textValue]// 此处参数对应原生 showCategoryName 办法的参数,从第二个开始
        );
    }

    render() {
        return <CategoryView>
            <View>
                {this.props.children}
            </View>
        </CategoryView>;
    }
}

export default Category;

如何应用:

import {Category} from 'local/Category';

<Category ref={ref => { this.categoryRef = ref}}>
    <TouchableWithoutFeedback onPress={() => {this.categoryRef.sendTextValue2Native('测试文本')
    }}>
        ...
    </TouchableWithoutFeedback>;
<Category />

这样在 Category 组件时,原生同样就会创立一个原生 CategoryView 的实例对象。这样在 RN 端调用 sendTextValue2Native 就能够将内容发送到原生的 showCategoryName 办法,而后在原生解决相干的逻辑。文章中的调用还是较为简单,波及到属性等更简单的应用能够参考文章:https://reactnative.cn/docs/n…

总结:
2 种通信形式利用的场景是不一样的,第一种双向通信应用绝对更加广泛,因为通信编写形式与 2 端不会有太多代码上的耦合度,第二种形式相对来说就和 UI 的应用绑定联合的更严密,限度也更多一些~

退出移动版