FLEXProperty.h 6.4 KB

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