diff --git a/React/Views/RCTComponentData.m b/React/Views/RCTComponentData.m index 91c92f94a60ffd..d11f5a2c84ca3d 100644 --- a/React/Views/RCTComponentData.m +++ b/React/Views/RCTComponentData.m @@ -383,6 +383,7 @@ - (void)setProps:(NSDictionary *)props forShadowView:(RCTShadowV - (NSDictionary *)viewConfig { + NSMutableDictionary *propTypes = [NSMutableDictionary new]; NSMutableArray *bubblingEvents = [NSMutableArray new]; NSMutableArray *directEvents = [NSMutableArray new]; @@ -395,42 +396,47 @@ - (void)setProps:(NSDictionary *)props forShadowView:(RCTShadowV } } #pragma clang diagnostic pop - - unsigned int count = 0; - NSMutableDictionary *propTypes = [NSMutableDictionary new]; - Method *methods = class_copyMethodList(object_getClass(_managerClass), &count); - for (unsigned int i = 0; i < count; i++) { - SEL selector = method_getName(methods[i]); - const char *selectorName = sel_getName(selector); - if (strncmp(selectorName, "propConfig", strlen("propConfig")) != 0) { - continue; - } - - // We need to handle both propConfig_* and propConfigShadow_* methods - const char *underscorePos = strchr(selectorName + strlen("propConfig"), '_'); - if (!underscorePos) { - continue; - } - - NSString *name = @(underscorePos + 1); - NSString *type = ((NSArray *(*)(id, SEL))objc_msgSend)(_managerClass, selector)[0]; - if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) { - RCTLogError(@"Property '%@' of component '%@' redefined from '%@' " - "to '%@'", name, _name, propTypes[name], type); - } - - if ([type isEqualToString:@"RCTBubblingEventBlock"]) { - [bubblingEvents addObject:RCTNormalizeInputEventName(name)]; - propTypes[name] = @"BOOL"; - } else if ([type isEqualToString:@"RCTDirectEventBlock"]) { - [directEvents addObject:RCTNormalizeInputEventName(name)]; - propTypes[name] = @"BOOL"; - } else { - propTypes[name] = type; + + Class superClass = _managerClass; + while (superClass && superClass != [RCTViewManager class]) { + if ([superClass isSubclassOfClass:[RCTViewManager class]]) { + unsigned int count = 0; + Method *methods = class_copyMethodList(object_getClass(superClass), &count); + for (unsigned int i = 0; i < count; i++) { + SEL selector = method_getName(methods[i]); + const char *selectorName = sel_getName(selector); + if (strncmp(selectorName, "propConfig", strlen("propConfig")) != 0) { + continue; + } + + // We need to handle both propConfig_* and propConfigShadow_* methods + const char *underscorePos = strchr(selectorName + strlen("propConfig"), '_'); + if (!underscorePos) { + continue; + } + + NSString *name = @(underscorePos + 1); + NSString *type = ((NSArray *(*)(id, SEL))objc_msgSend)(superClass, selector)[0]; + if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) { + RCTLogError(@"Property '%@' of component '%@' redefined from '%@' " + "to '%@'", name, _name, propTypes[name], type); + } + + if ([type isEqualToString:@"RCTBubblingEventBlock"]) { + [bubblingEvents addObject:RCTNormalizeInputEventName(name)]; + propTypes[name] = @"BOOL"; + } else if ([type isEqualToString:@"RCTDirectEventBlock"]) { + [directEvents addObject:RCTNormalizeInputEventName(name)]; + propTypes[name] = @"BOOL"; + } else { + propTypes[name] = type; + } + } + free(methods); } + superClass = [superClass superclass]; } - free(methods); - + #if RCT_DEBUG for (NSString *event in bubblingEvents) { if ([directEvents containsObject:event]) {