提问人:iUrii 提问时间:10/12/2023 更新时间:10/12/2023 访问量:81
如何在纯 Swift 中创建 React Native Module
How to create React Native Module in pure Swift
问:
我在React Native上有一个项目,它有一堆Native Modules和UI组件。代码主要是用 Swift 编写的,但它也有 Objective-C 代码,用于将我的 swift 的原生类和方法导出到 React Native,因为 Swift 不支持 C 宏,例如:
// Calendar.m
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(Calendar, NSObject)
RCT_EXTERN_METHOD(createEvent:(NSString *)title location:(NSString* )location)
@end
// Calendar.swift
@objc(Calendar)
class Calendar: NSObject {
@objc
func createEvent(_ title: String, location: String) {
print(title, location)
}
}
每次修改时同时管理 Objective-C 和 Swift 方法接口很不方便,那么有没有办法消除 Objective-C 代码?
答:
如果你研究 React Native 宏等,你会发现它们为 React Native 生成了额外的静态方法来注册你的模块并公开你的方法:RCT_EXTERN_MODULE
RCT_EXTERN_METHOD
#define RCT_EXPORT_MODULE_NO_LOAD(js_name, objc_name) \
RCT_EXTERN void RCTRegisterModule(Class); \
+(NSString *)moduleName \
{ \
return @ #js_name; \
} \
__attribute__((constructor)) static void RCT_CONCAT(initialize_, objc_name)() \
{ \
RCTRegisterModule([objc_name class]); \
}
#define _RCT_EXTERN_REMAP_METHOD(js_name, method, is_blocking_synchronous_method) \
+(const RCTMethodInfo *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) \
{ \
static RCTMethodInfo config = {#js_name, #method, is_blocking_synchronous_method}; \
return &config; \
}
您可以在 Swift 代码中实现以下方法:
import React
class Calendar: NSObject, RCTBridgeModule {
@objc func createEvent(_ title: String, location: String) {
print(title, location)
}
@objc static func __rct_export__createEvent() -> UnsafePointer<RCTMethodInfo>? {
struct Static {
static let jsName = strdup("createEvent")
static let objcName = strdup("createEvent:(NSString * _Nonnull)title location:(NSString * _Nonnull)location")
static var methodInfo = RCTMethodInfo(jsName: jsName, objcName: objcName, isSync: false)
}
return withUnsafePointer(to: &Static.methodInfo) {
$0
}
}
@objc class func moduleName() -> String! {
"\(self)"
}
}
此外,您需要在应用程序启动时手动注册您的类才能运行:
RCTRegisterModule(Calendar.self)
Swift 宏
正如你所看到的,在纯 Swift 中手动编写一个 React Native 模块是可能的,但它一点也不方便。但是宏已经开始支持 Swift 5.9 (XCode 15),您可以将 ReactBridge swift 宏库用于 React Native 模块和 UI 组件。有了这个库,你的代码就变成了:
import React
import ReactBridge
@ReactModule
class Calendar: NSObject, RCTBridgeModule {
@ReactMethod
@objc func createEvent(title: String, location: String) {
print(title, location)
}
}
如果您愿意使用expo,那么在它们处理所有讨厌的objc内容之前,我已经将其用于本机模块。Expo Modules API
他们希望你把你的模块写进去,但我相信在引擎盖下,他们仍然只是生成你需要的所有objc代码。Kotlin and Swift
Expo Modules API
这是一次很棒的经历,特别是如果你想写 swift 代码。我写了一个没有它的原生模块,觉得 objc 的东西很难与 swift 代码保持同步。
评论