react-native-navigation的迁移库

RNNOptions.m 2.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #import "RNNOptions.h"
  2. #import <objc/runtime.h>
  3. @implementation RNNOptions
  4. -(instancetype) initWithDict:(NSDictionary *)dict {
  5. self = [super init];
  6. [self initializeOptionsPropertiesWithDict:dict];
  7. [self mergeWith:dict];
  8. return self;
  9. }
  10. - (void)applyOn:(UIViewController *)viewController defaultOptions:(RNNOptions *)defaultOptions {
  11. [defaultOptions applyOn:viewController];
  12. [self applyOn:viewController];
  13. }
  14. -(void)mergeWith:(NSDictionary *)otherOptions {
  15. for (id key in otherOptions) {
  16. if ([self hasProperty:key]) {
  17. if ([[self valueForKey:key] isKindOfClass:[RNNOptions class]]) {
  18. RNNOptions* options = [self valueForKey:key];
  19. [options mergeWith:[otherOptions objectForKey:key]];
  20. } else {
  21. [self setValue:[otherOptions objectForKey:key] forKey:key];
  22. }
  23. }
  24. }
  25. }
  26. - (void)mergeOptions:(RNNOptions *)otherOptions overrideOptions:(BOOL)override {
  27. for (id prop in [self objectProperties:otherOptions]) {
  28. id value = [otherOptions valueForKey:prop];
  29. if ([value isKindOfClass:[RNNOptions class]]) {
  30. [[self valueForKey:prop] mergeOptions:value overrideOptions:override];
  31. } else if (value && (override || ![self valueForKey:prop])) {
  32. [self setValue:value forKey:prop];
  33. }
  34. }
  35. }
  36. - (void)mergeOptions:(RNNOptions *)otherOptions {
  37. [self mergeOptions:otherOptions overrideOptions:YES];
  38. }
  39. - (BOOL)hasProperty:(NSString*)propName {
  40. return [self respondsToSelector:NSSelectorFromString(propName)];
  41. }
  42. - (void)initializeOptionsPropertiesWithDict:(NSDictionary*)dict {
  43. unsigned int count;
  44. objc_property_t* props = class_copyPropertyList([self class], &count);
  45. for (int i = 0; i < count; i++) {
  46. objc_property_t property = props[i];
  47. NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
  48. const char * type = property_getAttributes(property);
  49. NSString * typeString = [NSString stringWithUTF8String:type];
  50. NSArray * attributes = [typeString componentsSeparatedByString:@","];
  51. NSString * typeAttribute = [attributes objectAtIndex:0];
  52. if ([typeAttribute hasPrefix:@"T@"] && [typeAttribute length] > 3) {
  53. NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)];
  54. Class typeClass = NSClassFromString(typeClassName);
  55. if ([typeClass isSubclassOfClass:[RNNOptions class]]) {
  56. RNNOptions* value = [[typeClass alloc] initWithDict:dict[propertyName]];
  57. [self setValue:value forKey:propertyName];
  58. }
  59. }
  60. }
  61. free(props);
  62. }
  63. - (NSArray *)objectProperties:(NSObject *)object {
  64. NSMutableArray* properties = [NSMutableArray new];
  65. unsigned int count;
  66. objc_property_t* props = class_copyPropertyList([object class], &count);
  67. for (int i = 0; i < count; i++) {
  68. objc_property_t property = props[i];
  69. NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
  70. [properties addObject:propertyName];
  71. }
  72. free(props);
  73. return properties;
  74. }
  75. @end