NSObject+MJClass.m 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // NSObject+MJClass.m
  3. // MJExtensionExample
  4. //
  5. // Created by MJ Lee on 15/8/11.
  6. // Copyright (c) 2015年 小码哥. All rights reserved.
  7. //
  8. #import "NSObject+MJClass.h"
  9. #import "NSObject+MJCoding.h"
  10. #import "NSObject+MJKeyValue.h"
  11. #import "MJFoundation.h"
  12. #import <objc/runtime.h>
  13. #import "MJDictionaryCache.h"
  14. static const char MJAllowedPropertyNamesKey = '\0';
  15. static const char MJIgnoredPropertyNamesKey = '\0';
  16. static const char MJAllowedCodingPropertyNamesKey = '\0';
  17. static const char MJIgnoredCodingPropertyNamesKey = '\0';
  18. @implementation NSObject (MJClass)
  19. + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration
  20. {
  21. // 1.没有block就直接返回
  22. if (enumeration == nil) return;
  23. // 2.停止遍历的标记
  24. BOOL stop = NO;
  25. // 3.当前正在遍历的类
  26. Class c = self;
  27. // 4.开始遍历每一个类
  28. while (c && !stop) {
  29. // 4.1.执行操作
  30. enumeration(c, &stop);
  31. // 4.2.获得父类
  32. c = class_getSuperclass(c);
  33. if ([MJFoundation isClassFromFoundation:c]) break;
  34. }
  35. }
  36. + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration
  37. {
  38. // 1.没有block就直接返回
  39. if (enumeration == nil) return;
  40. // 2.停止遍历的标记
  41. BOOL stop = NO;
  42. // 3.当前正在遍历的类
  43. Class c = self;
  44. // 4.开始遍历每一个类
  45. while (c && !stop) {
  46. // 4.1.执行操作
  47. enumeration(c, &stop);
  48. // 4.2.获得父类
  49. c = class_getSuperclass(c);
  50. }
  51. }
  52. #pragma mark - 属性黑名单配置
  53. + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames
  54. {
  55. [self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey];
  56. }
  57. + (NSMutableArray *)mj_totalIgnoredPropertyNames
  58. {
  59. return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey];
  60. }
  61. #pragma mark - 归档属性黑名单配置
  62. + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames
  63. {
  64. [self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey];
  65. }
  66. + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames
  67. {
  68. return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey];
  69. }
  70. #pragma mark - 属性白名单配置
  71. + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;
  72. {
  73. [self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey];
  74. }
  75. + (NSMutableArray *)mj_totalAllowedPropertyNames
  76. {
  77. return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey];
  78. }
  79. #pragma mark - 归档属性白名单配置
  80. + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames
  81. {
  82. [self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey];
  83. }
  84. + (NSMutableArray *)mj_totalAllowedCodingPropertyNames
  85. {
  86. return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey];
  87. }
  88. #pragma mark - block和方法处理:存储block的返回值
  89. + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key
  90. {
  91. if (block) {
  92. objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  93. } else {
  94. objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  95. }
  96. // 清空数据
  97. [[MJDictionaryCache dictWithDictId:key] removeAllObjects];
  98. }
  99. + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key
  100. {
  101. NSMutableArray *array = [MJDictionaryCache objectForKey:NSStringFromClass(self) forDictId:key];
  102. if (array) return array;
  103. // 创建、存储
  104. [MJDictionaryCache setObject:array = [NSMutableArray array] forKey:NSStringFromClass(self) forDictId:key];
  105. if ([self respondsToSelector:selector]) {
  106. #pragma clang diagnostic push
  107. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  108. NSArray *subArray = [self performSelector:selector];
  109. #pragma clang diagnostic pop
  110. if (subArray) {
  111. [array addObjectsFromArray:subArray];
  112. }
  113. }
  114. [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
  115. NSArray *subArray = objc_getAssociatedObject(c, key);
  116. [array addObjectsFromArray:subArray];
  117. }];
  118. return array;
  119. }
  120. @end