RN橋接原生iOS 最詳細(xì)的教程

一、先把「RN Bridge 是什么」想明白(非常關(guān)鍵)

1?? 流程

JS 線程(業(yè)務(wù)邏輯)
↓
Bridge(消息通道)
↓
Native 線程(iOS / Android)
↓
UI / 系統(tǒng)能力

重點(diǎn)一句話:

JS 和 iOS 不能直接互相調(diào)用方法,只能“發(fā)消息”

2?? RN Bridge 本質(zhì)是什么?

?? 一個(gè)異步的消息總線

消息里包含:
? 模塊名
? 方法名
? 參數(shù)(JSON)
? 回調(diào) / Promise 標(biāo)識(shí)

它不是函數(shù)調(diào)用,是“RPC”

3?? RN Bridge 能干什么 / 不能干什么

? 適合
? 調(diào)系統(tǒng)能力(相機(jī)、相冊(cè)、支付)
? 調(diào)原生 SDK
? 狀態(tài)通知(登錄成功、播放狀態(tài))

? 不適合
? 高頻調(diào)用(滾動(dòng)、動(dòng)畫(huà))
? 同步返回值
? 傳大對(duì)象 / 二進(jìn)制

二、最基礎(chǔ):JS 調(diào) iOS(無(wú)返回值)

Step 1:創(chuàng)建一個(gè) iOS 原生模塊

1?? 新建 OC 文件

ios/
 └── DeviceModule.h
 └── DeviceModule.m

2?? .h 文件

#import <React/RCTBridgeModule.h>
@interface DeviceModule : NSObject <RCTBridgeModule>
@end

?? 你在這里做了 2 件事:
? 引入 RN Bridge 協(xié)議
? 告訴 RN:這是個(gè)可被 JS 訪問(wèn)的模塊
3?? .m 文件(最關(guān)鍵)

#import "DeviceModule.h"
@implementation DeviceModule
RCT_EXPORT_MODULE(DeviceModule); //模塊名
RCT_EXPORT_METHOD(log:(NSString *)msg) {  //方法名 和 參數(shù)(JSON)
  NSLog(@"來(lái)自 RN 的消息:%@", msg);
}
@end

Step 2:JS 側(cè)調(diào)用

import { NativeModules } from 'react-native';
NativeModules.DeviceModule.log('Hello iOS');

流程

JS
 ↓
NativeModules.DeviceModule.log
 ↓
Bridge
 ↓
DeviceModule.m

Step 3:常見(jiàn)新手坑
? 方法寫(xiě)成實(shí)例方法沒(méi)問(wèn)題
? 但 不能有返回值

// ? 錯(cuò)
RCT_EXPORT_METHOD(getName) {
  return @"abc";
}

三、JS 調(diào) iOS(帶返回值)

RN 不能同步 return,只能:
? callback
? Promise(強(qiáng)烈推薦)

方式一:Callback(不推薦)

iOS

RCT_EXPORT_METHOD(getDeviceName:(RCTResponseSenderBlock)callback) {
  callback(@[@"iPhone 15"]);
}

JS

NativeModules.DeviceModule.getDeviceName(name => {
  console.log(name);
});

? 問(wèn)題:
? 易回調(diào)地獄
? 錯(cuò)誤處理不清晰

方式二:Promise(你以后 90% 用這個(gè))

iOS

RCT_EXPORT_METHOD(getDeviceName:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
  resolve(@"iPhone");
}

JS

const name = await NativeModules.DeviceModule.getDeviceName();

?? Promise 的規(guī)則
? resolve:成功
? reject:失敗
? JS 側(cè)可以 try/catch

四、JS ? iOS 參數(shù)支持哪些類(lèi)型?

? 支持(JSON 能表示的)


image.png

五、iOS 主線程 & 后臺(tái)線程(很容易卡)

默認(rèn)行為

RCT_EXPORT_METHOD(doSomething) {
  // 默認(rèn)在 **子線程**
}

如果你要更新 UI(必須主線程)

RCT_EXPORT_METHOD(showAlert) {
  dispatch_async(dispatch_get_main_queue(), ^{
    // UI 操作
  });
}

或者直接聲明

Objc 代碼
+ (BOOL)requiresMainQueueSetup {
  return YES;
}

?? 適合:
? 初始化 UIKit
? SDK 依賴(lài)主線程

六、Native 主動(dòng)通知 RN(事件機(jī)制)

這是 第二大核心能力
Step 1:繼承 RCTEventEmitter

#import <React/RCTEventEmitter.h>
@interface EventModule : RCTEventEmitter
@end

Step 2:聲明事件名

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

Step 3:發(fā)送事件

[self sendEventWithName:@"LoginSuccess"
                   body:@{@"uid": @"123"}];

Step 4:JS 監(jiān)聽(tīng)

import { NativeEventEmitter, NativeModules } from 'react-native';

const emitter = new NativeEventEmitter(NativeModules.EventModule);

emitter.addListener('LoginSuccess', data => {
  console.log(data.uid);
});

七、生命周期 & 常見(jiàn)使用場(chǎng)景


image.png

八、你現(xiàn)在就能寫(xiě)一個(gè)“合格”的橋接模塊了
最小模板(可直接復(fù)用)

@interface XXXModule : NSObject <RCTBridgeModule>
@end

@implementation XXXModule
RCT_EXPORT_MODULE

RCT_EXPORT_METHOD(action:(NSDictionary *)params
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
  resolve(@{@"success": @YES});
}
@end

swift使用

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

十、最小可復(fù)制模板(你可以直接存下來(lái))

Swift

@objc(DeviceModule)
class DeviceModule: NSObject {

  @objc
  func action(
    _ params: NSDictionary,
    resolver resolve: @escaping RCTPromiseResolveBlock,
    rejecter reject: @escaping RCTPromiseRejectBlock
  ) {
    resolve(["success": true])
  }
}

OC Bridge

@interface RCT_EXTERN_MODULE(DeviceModule, NSObject)

RCT_EXTERN_METHOD(
  action:(NSDictionary *)params
  resolver:(RCTPromiseResolveBlock)resolve
  rejecter:(RCTPromiseRejectBlock)reject
)

@end
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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