RN桥接原生iOS 最详细的教程

一、先把「RN Bridge 是什么」想明白(非常关键)

1️⃣ 流程

JS 线程(业务逻辑)
↓
Bridge(消息通道)
↓
Native 线程(iOS / Android)
↓
UI / 系统能力

重点一句话:

JS 和 iOS 不能直接互相调用方法,只能“发消息”

2️⃣ RN Bridge 本质是什么?

👉 一个异步的消息总线

消息里包含:
• 模块名
• 方法名
• 参数(JSON)
• 回调 / Promise 标识

它不是函数调用,是“RPC”

3️⃣ RN Bridge 能干什么 / 不能干什么

✅ 适合
• 调系统能力(相机、相册、支付)
• 调原生 SDK
• 状态通知(登录成功、播放状态)

❌ 不适合
• 高频调用(滚动、动画)
• 同步返回值
• 传大对象 / 二进制

二、最基础:JS 调 iOS(无返回值)

Step 1:创建一个 iOS 原生模块

1️⃣ 新建 OC 文件

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

2️⃣ .h 文件

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

📌 你在这里做了 2 件事:
• 引入 RN Bridge 协议
• 告诉 RN:这是个可被 JS 访问的模块
3️⃣ .m 文件(最关键)

#import "DeviceModule.h"
@implementation DeviceModule
RCT_EXPORT_MODULE(DeviceModule); //模块名
RCT_EXPORT_METHOD(log:(NSString *)msg) {  //方法名 和 参数(JSON)
  NSLog(@"来自 RN 的消息:%@", msg);
}
@end

Step 2:JS 侧调用

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

流程

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

Step 3:常见新手坑
❌ 方法写成实例方法没问题
❌ 但 不能有返回值

// ❌ 错
RCT_EXPORT_METHOD(getName) {
  return @"abc";
}

三、JS 调 iOS(带返回值)

RN 不能同步 return,只能:
• callback
• Promise(强烈推荐)

方式一:Callback(不推荐)

iOS

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

JS

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

❌ 问题:
• 易回调地狱
• 错误处理不清晰

方式二:Promise(你以后 90% 用这个)

iOS

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

JS

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

📌 Promise 的规则
• resolve:成功
• reject:失败
• JS 侧可以 try/catch

四、JS ↔ iOS 参数支持哪些类型?

✅ 支持(JSON 能表示的)


image.png

五、iOS 主线程 & 后台线程(很容易卡)

默认行为

RCT_EXPORT_METHOD(doSomething) {
  // 默认在 **子线程**
}

如果你要更新 UI(必须主线程)

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

或者直接声明

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

📌 适合:
• 初始化 UIKit
• SDK 依赖主线程

六、Native 主动通知 RN(事件机制)

这是 第二大核心能力
Step 1:继承 RCTEventEmitter

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

Step 2:声明事件名

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

Step 3:发送事件

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

Step 4:JS 监听

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

const emitter = new NativeEventEmitter(NativeModules.EventModule);

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

七、生命周期 & 常见使用场景


image.png

八、你现在就能写一个“合格”的桥接模块了
最小模板(可直接复用)

@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

十、最小可复制模板(你可以直接存下来)

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
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容