Swift原生与RN通信的实现

公司的工程是使用纯Swift开发的,正好我们最近的版本需要使用RN进行混编,官网不是很友好用的都是OC来实现的,这里我们用Swift来与RN进行通信,下面我们简单介绍,前提是您已经将RN集成到工程中,如果不知道怎么集成的可以查看官网或者中文网

环境:Xcode9、Swift4.0

RN调用iOS原生的方法

RNTestManagerBridge.h文件

1
2
3
4
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RNTestManagerBridge : NSObject<RCTBridgeModule>
@end

RNTestManagerBridge.m文件

1
2
3
4
5
6
7
#import "RNTestManagerBridge.h"
@implementation RNTestManagerBridge
RCT_EXPORT_MODULE(bingo);
RCT_EXPORT_METHOD(test){
NSLog(@"test------------");
}
@end

上面的bingo是自定义的模块名字,如果不填写默认为类名
在RN中调用,需要引用对应名字的桥接模块

1
2
var TestBridgeMoudle = NativeModules.bingo;
TestBridgeMoudle.test();

官方是使用宏定义RCT_EXPORT_METHOD将调用的原生方法声明,我们都知道Swift无法使用宏定义,所以我们需要让OC的桥接类在中间桥接Swift和RN。

我们使用Swift来写桥接类

先新建一个RNTestManagerBridge.swift文件

1
2
3
4
5
6
7
8
9
import Foundation

@objc(BridgeManager)
open class BridgeManager: NSObject {
@objc(test:)
func test(str : String) -> Void {

}
}

同样,这种写法也是可以的,因为OC中的方法调用是自动隐去了首个变量名,在使用@objc注册方法的时候如果方法的首个变量不使用_隐去的话,与RCT_EXTERN_METHOD注册的的方法无法对应

1
2
3
4
5
6
7
8
import Foundation

@objc(BridgeManager)
open class BridgeManager: NSObject {
@objc func test(_ str : String) -> Void {

}
}

接着,创建一个私有的实现文件,并将必要的信息注册到RN中:

1
2
3
4
5
6
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(BridgeManager, NSObject)
RCT_EXTERN_METHOD(test:(NSString *)str)
@end

需要一个额外的桥接头文件,用来导出Objective-C文件给Swift。如果你是通过Xcode菜单中的File>New File来创建的Swift文件,Xcode会自动为你创建这个头文件。在这个头文件中,你需要引入RCTBridgeModule.h。

1
#import <React/RCTBridgeModule.h>

同样的,你也可以使用RCT_EXTERN_REMAP_MODULERCT_EXTERN_REMAP_METHOD来改变导出模块和方法的JavaScript调用名称。 了解更多信息,请参阅RCTBridgeModule.