FLEXProperty.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //
  2. // FLEXProperty.h
  3. // FLEX
  4. //
  5. // Derived from MirrorKit.
  6. // Created by Tanner on 6/30/15.
  7. // Copyright (c) 2015 Tanner Bennett. All rights reserved.
  8. //
  9. #import <Foundation/Foundation.h>
  10. #import "FLEXRuntimeUtility.h"
  11. #import <objc/runtime.h>
  12. @class FLEXPropertyAttributes, FLEXMethodBase;
  13. #pragma mark FLEXProperty
  14. @interface FLEXProperty : NSObject
  15. /// You may use this initializer instead of \c property:onClass: if you don't need
  16. /// to know anything about the uniqueness of this property or where it comes from.
  17. + (instancetype)property:(objc_property_t)property;
  18. /// This initializer can be used to access additional information
  19. /// in an efficient manner. That information being whether this property
  20. /// is certainly not unique and the name of the binary image which declares it.
  21. /// @param cls the class, or metaclass if this is a class property.
  22. + (instancetype)property:(objc_property_t)property onClass:(Class)cls;
  23. /// @param cls the class, or metaclass if this is a class property
  24. + (instancetype)named:(NSString *)name onClass:(Class)cls;
  25. /// Constructs a new property with the given name and attributes.
  26. + (instancetype)propertyWithName:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes;
  27. /// \c 0 if the instance was created via \c +propertyWithName:attributes,
  28. /// otherwise this is the first property in \c objc_properties
  29. @property (nonatomic, readonly) objc_property_t objc_property;
  30. @property (nonatomic, readonly) objc_property_t *objc_properties;
  31. @property (nonatomic, readonly) NSInteger objc_propertyCount;
  32. @property (nonatomic, readonly) BOOL isClassProperty;
  33. /// The name of the property.
  34. @property (nonatomic, readonly) NSString *name;
  35. /// The type of the property. Get the full type from the attributes.
  36. @property (nonatomic, readonly) FLEXTypeEncoding type;
  37. /// The property's attributes.
  38. @property (nonatomic ) FLEXPropertyAttributes *attributes;
  39. /// The (likely) setter, regardless of whether the property is readonly.
  40. /// For example, this might be the custom setter.
  41. @property (nonatomic, readonly) SEL likelySetter;
  42. @property (nonatomic, readonly) NSString *likelySetterString;
  43. /// Not valid unless initialized with the owning class.
  44. @property (nonatomic, readonly) BOOL likelySetterExists;
  45. /// The (likely) getter. For example, this might be the custom getter.
  46. @property (nonatomic, readonly) SEL likelyGetter;
  47. @property (nonatomic, readonly) NSString *likelyGetterString;
  48. /// Not valid unless initialized with the owning class.
  49. @property (nonatomic, readonly) BOOL likelyGetterExists;
  50. /// Whether there are certainly multiple definitions of this property,
  51. /// such as in categories in other binary images or something.
  52. /// @return Whether \c objc_property matches the return value of \c class_getProperty,
  53. /// or \c NO if this property was not created with \c property:onClass
  54. @property (nonatomic, readonly) BOOL multiple;
  55. /// @return The bundle of the image that contains this property definition,
  56. /// or \c nil if this property was not created with \c property:onClass or
  57. /// if this property is probably defined in the objc runtime.
  58. @property (nonatomic, readonly) NSString *imageName;
  59. /// For internal use
  60. @property (nonatomic) id tag;
  61. /// @return The value of this property on \c target as given by \c -valueForKey:
  62. /// A source-like description of the property, with all of its attributes.
  63. @property (nonatomic, readonly) NSString *fullDescription;
  64. /// If this is a class property, you must class the class object.
  65. - (id)getValue:(id)target;
  66. /// Calls into -getValue: and passes that value into
  67. /// -[FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:type:]
  68. /// and returns the result.
  69. ///
  70. /// If this is a class property, you must class the class object.
  71. - (id)getPotentiallyUnboxedValue:(id)target;
  72. /// Safe to use regardless of how the \c FLEXProperty instance was initialized.
  73. ///
  74. /// This uses \c self.objc_property if it exists, otherwise it uses \c self.attributes
  75. - (objc_property_attribute_t *)copyAttributesList:(unsigned int *)attributesCount;
  76. /// Replace the attributes of the current property in the given class,
  77. /// using the attributes in \c self.attributes
  78. ///
  79. /// What happens when the property does not exist is undocumented.
  80. - (void)replacePropertyOnClass:(Class)cls;
  81. #pragma mark Convenience getters and setters
  82. /// @return A getter for the property with the given implementation.
  83. /// @discussion Consider using the \c FLEXPropertyGetter macros.
  84. - (FLEXMethodBase *)getterWithImplementation:(IMP)implementation;
  85. /// @return A setter for the property with the given implementation.
  86. /// @discussion Consider using the \c FLEXPropertySetter macros.
  87. - (FLEXMethodBase *)setterWithImplementation:(IMP)implementation;
  88. #pragma mark FLEXMethod property getter / setter macros
  89. // Easier than using the above methods yourself in most cases
  90. /// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and
  91. /// uses the \c FLEXProperty's \c attribute's \c backingIvarName to get the Ivar.
  92. #define FLEXPropertyGetter(FLEXProperty, type) [FLEXProperty \
  93. getterWithImplementation:imp_implementationWithBlock(^(id self) { \
  94. return *(type *)[self getIvarAddressByName:FLEXProperty.attributes.backingIvar]; \
  95. }) \
  96. ];
  97. /// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and
  98. /// uses the \c FLEXProperty's \c attribute's \c backingIvarName to set the Ivar.
  99. #define FLEXPropertySetter(FLEXProperty, type) [FLEXProperty \
  100. setterWithImplementation:imp_implementationWithBlock(^(id self, type value) { \
  101. [self setIvarByName:FLEXProperty.attributes.backingIvar value:&value size:sizeof(type)]; \
  102. }) \
  103. ];
  104. /// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and an Ivar name string to get the Ivar.
  105. #define FLEXPropertyGetterWithIvar(FLEXProperty, ivarName, type) [FLEXProperty \
  106. getterWithImplementation:imp_implementationWithBlock(^(id self) { \
  107. return *(type *)[self getIvarAddressByName:ivarName]; \
  108. }) \
  109. ];
  110. /// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and an Ivar name string to set the Ivar.
  111. #define FLEXPropertySetterWithIvar(FLEXProperty, ivarName, type) [FLEXProperty \
  112. setterWithImplementation:imp_implementationWithBlock(^(id self, type value) { \
  113. [self setIvarByName:ivarName value:&value size:sizeof(type)]; \
  114. }) \
  115. ];
  116. @end