/**
  * This function parses the exported methods inside RCTBridgeModules and
  * generates an array of arrays of RCTModuleMethod objects, keyed
  * by module index.
  */
 static RCTSparseArray *RCTExportedMethodsByModuleID(void)
 {
 static RCTSparseArray *methodsByModuleID;
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
  
 Dl_info info;
 dladdr(&RCTExportedMethodsByModuleID, &info);
  
 #ifdef __LP64__
 typedef uint64_t RCTExportValue;
 typedef struct section_64 RCTExportSection;
 #define RCTGetSectByNameFromHeader getsectbynamefromheader_64
 #else
 typedef uint32_t RCTExportValue;
 typedef struct section RCTExportSection;
 #define RCTGetSectByNameFromHeader getsectbynamefromheader
 #endif
  
 const RCTExportValue mach_header = (RCTExportValue)info.dli_fbase;
 const RCTExportSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTExport");
  
 if (section == NULL) {
 return;
 }
  
 NSArray *classes = RCTBridgeModuleClassesByModuleID();
 NSMutableDictionary *methodsByModuleClassName = [NSMutableDictionary dictionaryWithCapacity:[classes count]];
  
 for (RCTExportValue addr = section->offset;
 addr < section->offset + section->size;
 addr += sizeof(const char **) * 2) {
  
 // Get data entry
 const char **entries = (const char **)(mach_header + addr);
  
 // Create method
 RCTModuleMethod *moduleMethod =
 [[RCTModuleMethod alloc] initWithMethodName:@(entries[0])
 JSMethodName:strlen(entries[1]) ? @(entries[1]) : nil];
  
 // Cache method
 NSArray *methods = methodsByModuleClassName[moduleMethod.moduleClassName];
 methodsByModuleClassName[moduleMethod.moduleClassName] =
 methods ? [methods arrayByAddingObject:moduleMethod] : @[moduleMethod];
 }
  
 methodsByModuleID = [[RCTSparseArray alloc] initWithCapacity:[classes count]];
 [classes enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
 methodsByModuleID[moduleID] = methodsByModuleClassName[NSStringFromClass(moduleClass)];
 }];
 });
  
 return methodsByModuleID;
 }
05-12 09:56