React Native調(diào)用iOS原生UI組件的方法

在RN中文網(wǎng)的原生UI組件章節(jié): iOS Android,我們知道如何封裝原生UI組件給Javascript 端使用,如何導(dǎo)出屬性,如何設(shè)置事件回調(diào)、樣式等,但是View難免會(huì)有一些公有方法,翻遍官方文檔卻怎么也找不到相關(guān)描述,我在這里做個(gè)導(dǎo)出UI組件方法的記錄。

假如現(xiàn)在有個(gè)自定義View “LLCustomView” 想要封裝給React Native的js調(diào)用。

#import <UIKit/UIKit.h>

@interface LLCustomView : UIView

- (void)textFunc;

@end
#import "LLCustomView.h"

@implementation LLCustomView

- (void)textFunc {
    NSLog(@"%s", __FUNCTION__);
}

@end
  • 新建一個(gè)文件繼承自RCTViewManager的文件,文件名為視圖名稱+Manager,
  • 在實(shí)現(xiàn)文件里添加RCT_EXPORT_MODULE()標(biāo)記宏,讓模塊接口暴露給JavaScript
  • 實(shí)現(xiàn)-(UIView )view方法,并返回組件視圖
    原生View的frame或backgroundColor屬性這里就不用設(shè)置了,為了兩端統(tǒng)一,JavaScript 端的布局屬性會(huì)覆蓋原生屬性。
#import <React/RCTViewManager.h>

@interface LLCustomViewManager : RCTViewManager

@end
#import "LLCustomViewManager.h"
#import <React/RCTUIManager.h>
#import "LLCustomView.h"

@interface LLCustomViewManager ()

@property (nonatomic, strong) LLCustomView *customView;

@end


@implementation LLCustomViewManager

RCT_EXPORT_MODULE()

- (UIView *)view {
    _customView = [[LLCustomView alloc] initWithFrame:CGRectZero];
    return _customView;
}

RCT_EXPORT_METHOD(textFunc:(nonnull NSNumber *)reactTag) {
    [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
        LLCustomView *view = viewRegistry[reactTag];
        if (![view isKindOfClass:[LLCustomView class]]) {
            RCTLogError(@"Invalid view returned from registry, expecting LLCustomView, got: %@", view);
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                LLCustomView *bannerView = (LLCustomView *)viewRegistry[reactTag];
                [bannerView textFunc];
            });
        }
    }];
}

@end

JavaScript

當(dāng)js端需要封裝時(shí):


image.png

1和6對(duì)應(yīng)原生模塊;
4為直接導(dǎo)出的組件名稱,4和5名稱必須一致;
注意當(dāng)js端需要封裝UI組件時(shí),我們?cè)趓equireNativeComponent增加第二個(gè)參數(shù)從 null 變成了用于封裝的組件CustomView。這使得 React Native 的底層框架可以檢查原生屬性和包裝類的屬性是否一致,來減少出現(xiàn)問題的可能。

使用UIManager模塊的dispatchViewManagerCommand方法,JS端可以調(diào)用Native的View方法,

  • findNodeHandle方法是在React中定義,可以找到組件實(shí)例的reactTag(執(zhí)行在JS端),UIManager可以把調(diào)用命令分發(fā)到Native端對(duì)應(yīng)的組件類型的ViewManager,再通過ViewManager調(diào)用View組件實(shí)例的對(duì)應(yīng)方法。
  • 通過UIManager.LLCustomView.Commands找到模塊數(shù)據(jù)結(jié)構(gòu),不過新版提示這個(gè)將被廢棄,使用UIManager.getViewManagerConfig('LLCustomView').Commands代替。
  • 第三個(gè)參數(shù),要傳給原生UI組件方法的參數(shù)

CustomView.js

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {requireNativeComponent, findNodeHandle, UIManager} from 'react-native';
import console = require('console');

var LLCustomView = requireNativeComponent('LLCustomView', CustomView);

export default class CustomView extends Component {

    static propTypes = {};
    static defaultProps = {};

    render() {
        return <LLCustomView {...this.props} />;
    }

    textFunc = () => {
        UIManager.dispatchViewManagerCommand(
            findNodeHandle(this),
            UIManager.getViewManagerConfig('LLCustomView').Commands.textFunc,
            null
        );
    };
}

調(diào)用

<Button title='click' onPress={()=>{
          this.customViewRef && this.customViewRef.textFunc();
        }}/>

控制臺(tái)輸出

-[LLCustomView textFunc]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容