Tanner Bennett лет назад: 6
Родитель
Сommit
2dee6901f7

+ 9 - 1
Classes/Utility/Categories/NSObject+Reflection.h

@@ -19,7 +19,12 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param returnType The encoded return type. \c void for exmaple would be \c @encode(void).
 /// @param count The number of parameters in this type encoding string.
 /// @return The type encoding string, or \c nil if \e returnType is \c NULL.
-extern NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...);
+NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...);
+
+NSArray<Class> *FLEXGetAllSubclasses(_Nullable Class cls, BOOL includeSelf);
+NSArray<Class> *FLEXGetClassHierarchy(_Nullable Class cls, BOOL includeSelf);
+NSArray<FLEXProtocol *> *FLEXGetConformedProtocols(_Nullable Class cls);
+
 
 #pragma mark Reflection
 @interface NSObject (Reflection)
@@ -27,6 +32,7 @@ extern NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger coun
 @property (nonatomic, readonly       ) FLEXMirror *flex_reflection;
 @property (nonatomic, readonly, class) FLEXMirror *flex_reflection;
 
+/// Calls into /c FLEXGetAllSubclasses
 /// @return Every subclass of the receiving class, including the receiver itself.
 @property (nonatomic, readonly, class) NSArray<Class> *flex_allSubclasses;
 
@@ -42,10 +48,12 @@ extern NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger coun
 /// @return The old superclass.
 + (Class)flex_setSuperclass:(Class)superclass;
 
+/// Calls into \c FLEXGetClassHierarchy()
 /// @return a list of classes going up the class hierarchy,
 /// starting with the receiver and ending with the root class.
 @property (nonatomic, readonly, class) NSArray<Class> *flex_classHierarchy;
 
+/// Calls into \c FLEXGetConformedProtocols
 /// @return a list of protocols this class itself conforms to.
 @property (nonatomic, readonly, class) NSArray<FLEXProtocol *> *flex_protocols;
 

+ 68 - 38
Classes/Utility/Categories/NSObject+Reflection.m

@@ -36,6 +36,71 @@ NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...)
     return encoding.copy;
 }
 
+NSArray<Class> *FLEXGetAllSubclasses(Class cls, BOOL includeSelf) {
+    if (!cls) {
+        return nil;
+    }
+    
+    Class *buffer = NULL;
+    
+    int count, size;
+    do {
+        count  = objc_getClassList(NULL, 0);
+        buffer = (Class *)realloc(buffer, count * sizeof(*buffer));
+        size   = objc_getClassList(buffer, count);
+    } while (size != count);
+    
+    NSMutableArray *classes = [NSMutableArray array];
+    if (includeSelf) {
+        [classes addObject:cls];
+    }
+    
+    for (int i = 0; i < count; i++) {
+        Class candidate = buffer[i];
+        Class superclass = candidate;
+        while ((superclass = class_getSuperclass(superclass))) {
+            if (superclass == cls) {
+                [classes addObject:candidate];
+                break;
+            }
+        }
+    }
+    
+    free(buffer);
+    return classes.copy;
+}
+
+NSArray<Class> *FLEXGetClassHierarchy(Class cls, BOOL includeSelf) {
+    if (!cls) {
+        return nil;
+    }
+    
+    NSMutableArray *classes = [NSMutableArray array];
+    if (includeSelf) {
+        [classes addObject:cls];
+    }
+    
+    while ((cls = [cls superclass])) {
+        [classes addObject:cls];
+    };
+
+    return classes.copy;
+}
+
+NSArray<FLEXProtocol *> *FLEXGetConformedProtocols(Class cls) {
+    if (!cls) {
+        return nil;
+    }
+    
+    unsigned int count = 0;
+    Protocol *__unsafe_unretained *list = class_copyProtocolList(cls, &count);
+    NSArray<Protocol *> *protocols = [NSArray arrayWithObjects:list count:count];
+    
+    return [protocols flex_mapped:^id(Protocol *pro, NSUInteger idx) {
+        return [FLEXProtocol protocol:pro];
+    }];
+}
+
 
 #pragma mark NSProxy
 
@@ -89,30 +154,7 @@ NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...)
 
 /// Code borrowed from MAObjCRuntime by Mike Ash
 + (NSArray *)flex_allSubclasses {
-    Class *buffer = NULL;
-    
-    int count, size;
-    do {
-        count  = objc_getClassList(NULL, 0);
-        buffer = (Class *)realloc(buffer, count * sizeof(*buffer));
-        size   = objc_getClassList(buffer, count);
-    } while (size != count);
-    
-    NSMutableArray *array = [NSMutableArray array];
-    for (int i = 0; i < count; i++) {
-        Class candidate = buffer[i];
-        Class superclass = candidate;
-        while (superclass) {
-            if (superclass == self) {
-                [array addObject:candidate];
-                break;
-            }
-            superclass = class_getSuperclass(superclass);
-        }
-    }
-    
-    free(buffer);
-    return array;
+    return FLEXGetAllSubclasses(self, YES);
 }
 
 - (Class)flex_setClass:(Class)cls {
@@ -135,23 +177,11 @@ NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...)
 }
 
 + (NSArray<Class> *)flex_classHierarchy {
-    NSMutableArray *classes = [NSMutableArray array];
-    Class cls = self;
-    do {
-        [classes addObject:cls];
-    } while ((cls = [cls superclass]));
-
-    return classes.copy;
+    return FLEXGetClassHierarchy(self, YES);
 }
 
 + (NSArray<FLEXProtocol *> *)flex_protocols {
-    unsigned int count = 0;
-    Protocol *__unsafe_unretained *list = class_copyProtocolList(self, &count);
-    NSArray<Protocol *> *protocols = [NSArray arrayWithObjects:list count:count];
-    
-    return [protocols flex_mapped:^id(Protocol *pro, NSUInteger idx) {
-        return [FLEXProtocol protocol:pro];
-    }];
+    return FLEXGetConformedProtocols(self);
 }
 
 @end