FLEXMirror.m 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //
  2. // FLEXMirror.m
  3. // FLEX
  4. //
  5. // Derived from MirrorKit.
  6. // Created by Tanner on 6/29/15.
  7. // Copyright (c) 2015 Tanner Bennett. All rights reserved.
  8. //
  9. #import "FLEXMirror.h"
  10. #import "FLEXProperty.h"
  11. #import "FLEXMethod.h"
  12. #import "FLEXIvar.h"
  13. #import "FLEXProtocol.h"
  14. #import "FLEXUtility.h"
  15. //#import "MirrorKit.h"
  16. //#import "NSObject+Reflection.h"
  17. #pragma mark FLEXMirror
  18. @implementation FLEXMirror
  19. - (id)init {
  20. [NSException
  21. raise:NSInternalInconsistencyException
  22. format:@"Class instance should not be created with -init"
  23. ];
  24. return nil;
  25. }
  26. #pragma mark Initialization
  27. + (instancetype)reflect:(id)objectOrClass {
  28. return [[self alloc] initWithValue:objectOrClass];
  29. }
  30. - (id)initWithValue:(id)value {
  31. NSParameterAssert(value);
  32. self = [super init];
  33. if (self) {
  34. _value = value;
  35. [self examine];
  36. }
  37. return self;
  38. }
  39. - (NSString *)description {
  40. NSString *type = self.isClass ? @"metaclass" : @"class";
  41. return [NSString
  42. stringWithFormat:@"<%@ %@=%@, %lu properties, %lu ivars, %lu methods, %lu protocols>",
  43. NSStringFromClass(self.class),
  44. type,
  45. self.className,
  46. (unsigned long)self.properties.count,
  47. (unsigned long)self.ivars.count,
  48. (unsigned long)self.methods.count,
  49. (unsigned long)self.protocols.count
  50. ];
  51. }
  52. - (void)examine {
  53. // cls is a metaclass if self.value is a class
  54. Class cls = object_getClass(self.value);
  55. unsigned int pcount, mcount, ivcount, pccount;
  56. objc_property_t *objcproperties = class_copyPropertyList(cls, &pcount);
  57. Protocol*__unsafe_unretained *procs = class_copyProtocolList(cls, &pccount);
  58. Method *objcmethods = class_copyMethodList(cls, &mcount);
  59. Ivar *objcivars = class_copyIvarList(cls, &ivcount);
  60. _className = NSStringFromClass(cls);
  61. _isClass = class_isMetaClass(cls); // or object_isClass(self.value)
  62. NSMutableArray *properties = [NSMutableArray array];
  63. for (int i = 0; i < pcount; i++)
  64. [properties addObject:[FLEXProperty property:objcproperties[i]]];
  65. _properties = properties;
  66. NSMutableArray *methods = [NSMutableArray array];
  67. for (int i = 0; i < mcount; i++)
  68. [methods addObject:[FLEXMethod method:objcmethods[i]]];
  69. _methods = methods;
  70. NSMutableArray *ivars = [NSMutableArray array];
  71. for (int i = 0; i < ivcount; i++)
  72. [ivars addObject:[FLEXIvar ivar:objcivars[i]]];
  73. _ivars = ivars;
  74. NSMutableArray *protocols = [NSMutableArray array];
  75. for (int i = 0; i < pccount; i++)
  76. [protocols addObject:[FLEXProtocol protocol:procs[i]]];
  77. _protocols = protocols;
  78. // Cleanup
  79. free(objcproperties);
  80. free(objcmethods);
  81. free(objcivars);
  82. free(procs);
  83. procs = NULL;
  84. }
  85. #pragma mark Misc
  86. - (FLEXMirror *)superMirror {
  87. return [FLEXMirror reflect:[self.value superclass]];
  88. }
  89. @end
  90. #pragma mark ExtendedMirror
  91. @implementation FLEXMirror (ExtendedMirror)
  92. - (id)filter:(NSArray *)array forName:(NSString *)name {
  93. NSPredicate *filter = [NSPredicate predicateWithFormat:@"%K = %@", @"name", name];
  94. return [array filteredArrayUsingPredicate:filter].firstObject;
  95. }
  96. - (FLEXMethod *)methodNamed:(NSString *)name {
  97. return [self filter:self.methods forName:name];
  98. }
  99. - (FLEXProperty *)propertyNamed:(NSString *)name {
  100. return [self filter:self.properties forName:name];
  101. }
  102. - (FLEXIvar *)ivarNamed:(NSString *)name {
  103. return [self filter:self.ivars forName:name];
  104. }
  105. - (FLEXProtocol *)protocolNamed:(NSString *)name {
  106. return [self filter:self.protocols forName:name];
  107. }
  108. @end