From 2d1b5d23c995bbfb5a88ba753a99312f5fd12df8 Mon Sep 17 00:00:00 2001 From: Alfred Zien Date: Sun, 31 Mar 2019 22:36:30 -0700 Subject: [PATCH] Use constructor attribute instead of +load objc method (#24155) Summary: Xcode 10.2 forbids creating categories for swift class that uses `+load` method. In react-native categories like this are used to register swift classes as modules (macro `RCT_EXTERN_MODULE`) This PR changes it to use `__attribute__((constructor))` instead of objc `+load` method. I introduced new macro for this purpose, `RCT_EXPORT_MODULE_NO_LOAD`, it expands in something like: ``` void RCTRegisterModule(Class); + (NSString *)moduleName { return @"jsNameFoo"; } __attribute__((constructor)) static void initialize_ObjcClassFoo{ RCTRegisterModule([ObjcClassFoo class]); } ``` Functions marked with `__attribute__((constructor))` are run before main and after all `+load` methods, so it seems like correct thing to do. Fixes https://github.com/facebook/react-native/issues/24139 Doc about loading order https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc [iOS] [Fixed] - Fix runtime crash in xcode 10.2 when using RCT_EXTERN_MODULE for swift classes. Pull Request resolved: https://github.com/facebook/react-native/pull/24155 Reviewed By: javache Differential Revision: D14668235 Pulled By: shergin fbshipit-source-id: 0c19e69ce2a68327387809773848d4ecd36d7461 (cherry picked from commit ff66600224e78fec5d0e902f8a035b78ed31a961) --- React/Base/RCTBridgeModule.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 1ab00bb5cfb0c4..15f2cc67852f8e 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -75,6 +75,17 @@ RCT_EXTERN void RCTRegisterModule(Class); \ + (NSString *)moduleName { return @#js_name; } \ + (void)load { RCTRegisterModule(self); } +/** + * Same as RCT_EXPORT_MODULE, but uses __attribute__((constructor)) for module + * registration. Useful for registering swift classes that forbids use of load + * Used in RCT_EXTERN_REMAP_MODULE + */ +#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]); } + // Implemented by RCT_EXPORT_MODULE + (NSString *)moduleName; @@ -237,7 +248,7 @@ RCT_EXTERN void RCTRegisterModule(Class); \ @interface objc_name (RCTExternModule) \ @end \ @implementation objc_name (RCTExternModule) \ - RCT_EXPORT_MODULE(js_name) + RCT_EXPORT_MODULE_NO_LOAD(js_name, objc_name) /** * Use this macro in accordance with RCT_EXTERN_MODULE to export methods