Просмотр исходного кода

Misc FLEX*Utility changes

Also don't load NSProxy categories if testing
Tanner Bennett лет назад: 6
Родитель
Сommit
87a821903d

+ 2 - 1
Classes/Utility/Categories/NSObject+Reflection.m

@@ -16,6 +16,7 @@
 #import "FLEXProtocol.h"
 #import "FLEXPropertyAttributes.h"
 #import "NSArray+Functional.h"
+#import "FLEXUtility.h"
 
 
 NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...) {
@@ -41,7 +42,7 @@ NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...)
 @interface NSProxy (AnyObjectAdditions) @end
 @implementation NSProxy (AnyObjectAdditions)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     // We need to get all of the methods in this file and add them to NSProxy. 
     // To do this we we need the class itself and it's metaclass.
     // Edit: also add them to Swift._SwiftObject

+ 3 - 0
Classes/Utility/FLEXUtility.h

@@ -17,6 +17,9 @@
 #import "UIFont+FLEX.h"
 #import "NSMapTable+FLEX_Subscripting.h"
 
+// Used to prevent loading of pre-registered shortcuts and runtime categories in a test environment
+#define FLEX_EXIT_IF_TESTING() if (NSClassFromString(@"XCTest")) return;
+
 /// Rounds down to the nearest "point" coordinate
 NS_INLINE CGFloat FLEXFloor(CGFloat x) {
     return floor(UIScreen.mainScreen.scale * (x)) / UIScreen.mainScreen.scale;

+ 27 - 1
Classes/Utility/Runtime/FLEXRuntimeUtility.h

@@ -77,6 +77,32 @@ typedef NS_ENUM(char, FLEXTypeEncoding) {
 #define FLEXEncodeClass(class) ("@\"" #class "\"")
 #define FLEXEncodeObject(obj) (obj ? [NSString stringWithFormat:@"@\"%@\"", [obj class]].UTF8String : @encode(id))
 
+#define PropertyKey(suffix) kFLEXPropertyAttributeKey##suffix : @""
+#define PropertyKeyGetter(getter) kFLEXPropertyAttributeKeyCustomGetter : NSStringFromSelector(@selector(getter))
+#define PropertyKeySetter(setter) kFLEXPropertyAttributeKeyCustomSetter : NSStringFromSelector(@selector(setter))
+
+/// Takes: min iOS version, property name, target class, property type, and a list of attributes
+#define FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, type, ...) ({ \
+    if (@available(iOS iOS_atLeast, *)) { \
+        NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithDictionary:@{ \
+            kFLEXPropertyAttributeKeyTypeEncoding : @(type), \
+            __VA_ARGS__ \
+        }]; \
+        [FLEXRuntimeUtility \
+            tryAddPropertyWithName:#name \
+            attributes:attrs \
+            toClass:cls \
+        ]; \
+    } \
+})
+
+/// Takes: min iOS version, property name, target class, property type, and a list of attributes
+#define FLEXRuntimeUtilityTryAddNonatomicProperty(iOS_atLeast, name, cls, type, ...) \
+    FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, @encode(type), PropertyKey(NonAtomic), __VA_ARGS__);
+/// Takes: min iOS version, property name, target class, property type (class name), and a list of attributes
+#define FLEXRuntimeUtilityTryAddObjectProperty(iOS_atLeast, name, cls, type, ...) \
+    FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, FLEXEncodeClass(type), PropertyKey(NonAtomic), __VA_ARGS__);
+
 @interface FLEXRuntimeUtility : NSObject
 
 // General Helpers
@@ -100,7 +126,7 @@ typedef NS_ENUM(char, FLEXTypeEncoding) {
 + (NSString *)safeDebugDescriptionForObject:(id)object;
 
 // Property Helpers
-+ (void)tryAddPropertyWithName:(const char *)name
++ (BOOL)tryAddPropertyWithName:(const char *)name
                     attributes:(NSDictionary<NSString *, NSString *> *)attributePairs
                        toClass:(__unsafe_unretained Class)theClass;
 + (NSArray<NSString *> *)allPropertyAttributeKeys;

+ 7 - 2
Classes/Utility/Runtime/FLEXRuntimeUtility.m

@@ -184,7 +184,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
 
 #pragma mark - Property Helpers (Public)
 
-+ (void)tryAddPropertyWithName:(const char *)name
++ (BOOL)tryAddPropertyWithName:(const char *)name
                     attributes:(NSDictionary<NSString *, NSString *> *)attributePairs
                        toClass:(__unsafe_unretained Class)theClass {
     objc_property_t property = class_getProperty(theClass, name);
@@ -200,10 +200,15 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
                 attributes[attributeIndex++] = attribute;
             }
 
-            class_addProperty(theClass, name, attributes, totalAttributesCount);
+            BOOL success = class_addProperty(theClass, name, attributes, totalAttributesCount);
             free(attributes);
+            return success;
+        } else {
+            return NO;
         }
     }
+    
+    return YES;
 }
 
 + (NSArray<NSString *> *)allPropertyAttributeKeys {

+ 1 - 0
Classes/Utility/Runtime/Objc/FLEXProperty.m

@@ -44,6 +44,7 @@
 }
 
 + (instancetype)named:(NSString *)name onClass:(Class)cls {
+    NSParameterAssert(class_getProperty(cls, name.UTF8String));
     return [self property:class_getProperty(cls, name.UTF8String) onClass:cls];
 }