NSObject+Lookin.m 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //
  2. // NSObject+Lookin.m
  3. // Lookin
  4. //
  5. // Created by Li Kai on 2018/12/22.
  6. // https://lookin.work
  7. //
  8. #import "NSObject+Lookin.h"
  9. #import <Objc/runtime.h>
  10. #import "TargetConditionals.h"
  11. #import "LookinWeakContainer.h"
  12. @implementation NSObject (Lookin)
  13. #pragma mark - Data Bind
  14. static char kAssociatedObjectKey_LookinAllBindObjects;
  15. - (NSMutableDictionary<id, id> *)lookin_allBindObjects {
  16. NSMutableDictionary<id, id> *dict = objc_getAssociatedObject(self, &kAssociatedObjectKey_LookinAllBindObjects);
  17. if (!dict) {
  18. dict = [NSMutableDictionary dictionary];
  19. objc_setAssociatedObject(self, &kAssociatedObjectKey_LookinAllBindObjects, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  20. }
  21. return dict;
  22. }
  23. - (void)lookin_bindObject:(id)object forKey:(NSString *)key {
  24. if (!key.length) {
  25. NSAssert(NO, @"");
  26. return;
  27. }
  28. @synchronized (self) {
  29. if (object) {
  30. [[self lookin_allBindObjects] setObject:object forKey:key];
  31. } else {
  32. [[self lookin_allBindObjects] removeObjectForKey:key];
  33. }
  34. }
  35. }
  36. - (id)lookin_getBindObjectForKey:(NSString *)key {
  37. if (!key.length) {
  38. NSAssert(NO, @"");
  39. return nil;
  40. }
  41. @synchronized (self) {
  42. id storedObj = [[self lookin_allBindObjects] objectForKey:key];
  43. if ([storedObj isKindOfClass:[LookinWeakContainer class]]) {
  44. storedObj = [(LookinWeakContainer *)storedObj object];
  45. }
  46. return storedObj;
  47. }
  48. }
  49. - (void)lookin_bindObjectWeakly:(id)object forKey:(NSString *)key {
  50. if (!key.length) {
  51. NSAssert(NO, @"");
  52. return;
  53. }
  54. if (object) {
  55. LookinWeakContainer *container = [[LookinWeakContainer alloc] init];
  56. container.object = object;
  57. [self lookin_bindObject:container forKey:key];
  58. } else {
  59. [self lookin_bindObject:nil forKey:key];
  60. }
  61. }
  62. - (void)lookin_bindDouble:(double)doubleValue forKey:(NSString *)key {
  63. [self lookin_bindObject:@(doubleValue) forKey:key];
  64. }
  65. - (double)lookin_getBindDoubleForKey:(NSString *)key {
  66. id object = [self lookin_getBindObjectForKey:key];
  67. if ([object isKindOfClass:[NSNumber class]]) {
  68. double doubleValue = [(NSNumber *)object doubleValue];
  69. return doubleValue;
  70. } else {
  71. return 0.0;
  72. }
  73. }
  74. - (void)lookin_bindBOOL:(BOOL)boolValue forKey:(NSString *)key {
  75. [self lookin_bindObject:@(boolValue) forKey:key];
  76. }
  77. - (BOOL)lookin_getBindBOOLForKey:(NSString *)key {
  78. id object = [self lookin_getBindObjectForKey:key];
  79. if ([object isKindOfClass:[NSNumber class]]) {
  80. BOOL boolValue = [(NSNumber *)object boolValue];
  81. return boolValue;
  82. } else {
  83. return NO;
  84. }
  85. }
  86. - (void)lookin_bindLong:(long)longValue forKey:(NSString *)key {
  87. [self lookin_bindObject:@(longValue) forKey:key];
  88. }
  89. - (long)lookin_getBindLongForKey:(NSString *)key {
  90. id object = [self lookin_getBindObjectForKey:key];
  91. if ([object isKindOfClass:[NSNumber class]]) {
  92. long longValue = [(NSNumber *)object longValue];
  93. return longValue;
  94. } else {
  95. return 0;
  96. }
  97. }
  98. - (void)lookin_bindPoint:(CGPoint)pointValue forKey:(NSString *)key {
  99. #if TARGET_OS_IPHONE
  100. [self lookin_bindObject:[NSValue valueWithCGPoint:pointValue] forKey:key];
  101. #elif TARGET_OS_MAC
  102. NSPoint nsPoint = NSMakePoint(pointValue.x, pointValue.y);
  103. [self lookin_bindObject:[NSValue valueWithPoint:nsPoint] forKey:key];
  104. #endif
  105. }
  106. - (CGPoint)lookin_getBindPointForKey:(NSString *)key {
  107. id object = [self lookin_getBindObjectForKey:key];
  108. if ([object isKindOfClass:[NSValue class]]) {
  109. #if TARGET_OS_IPHONE
  110. CGPoint pointValue = [(NSValue *)object CGPointValue];
  111. #elif TARGET_OS_MAC
  112. NSPoint nsPointValue = [(NSValue *)object pointValue];
  113. CGPoint pointValue = CGPointMake(nsPointValue.x, nsPointValue.y);
  114. #endif
  115. return pointValue;
  116. } else {
  117. return CGPointZero;
  118. }
  119. }
  120. - (void)lookin_clearBindForKey:(NSString *)key {
  121. [self lookin_bindObject:nil forKey:key];
  122. }
  123. @end
  124. @implementation NSObject (Lookin_Coding)
  125. - (id)lookin_encodedObjectWithType:(LookinCodingValueType)type {
  126. if (type == LookinCodingValueTypeColor) {
  127. if ([self isKindOfClass:[LookinColor class]]) {
  128. CGFloat r, g, b, a;
  129. #if TARGET_OS_IPHONE
  130. CGFloat white;
  131. if ([(UIColor *)self getRed:&r green:&g blue:&b alpha:&a]) {
  132. // valid
  133. } else if ([(UIColor *)self getWhite:&white alpha:&a]) {
  134. r = white;
  135. g = white;
  136. b = white;
  137. } else {
  138. NSAssert(NO, @"");
  139. r = 0;
  140. g = 0;
  141. b = 0;
  142. a = 0;
  143. }
  144. #elif TARGET_OS_MAC
  145. NSColor *color = [((NSColor *)self) colorUsingColorSpace:NSColorSpace.sRGBColorSpace];
  146. [color getRed:&r green:&g blue:&b alpha:&a];
  147. #endif
  148. NSArray<NSNumber *> *rgba = @[@(r), @(g), @(b), @(a)];
  149. return rgba;
  150. } else {
  151. NSAssert(NO, @"");
  152. return nil;
  153. }
  154. } else if (type == LookinCodingValueTypeImage) {
  155. #if TARGET_OS_IPHONE
  156. if ([self isKindOfClass:[UIImage class]]) {
  157. UIImage *image = (UIImage *)self;
  158. return UIImagePNGRepresentation(image);
  159. } else {
  160. NSAssert(NO, @"");
  161. return nil;
  162. }
  163. #elif TARGET_OS_MAC
  164. if ([self isKindOfClass:[NSImage class]]) {
  165. NSImage *image = (NSImage *)self;
  166. return [image TIFFRepresentation];
  167. } else {
  168. NSAssert(NO, @"");
  169. return nil;
  170. }
  171. #endif
  172. } else {
  173. return self;
  174. }
  175. }
  176. - (id)lookin_decodedObjectWithType:(LookinCodingValueType)type {
  177. if (type == LookinCodingValueTypeColor) {
  178. if ([self isKindOfClass:[NSArray class]]) {
  179. NSArray<NSNumber *> *rgba = (NSArray *)self;
  180. CGFloat r = [rgba[0] doubleValue];
  181. CGFloat g = [rgba[1] doubleValue];
  182. CGFloat b = [rgba[2] doubleValue];
  183. CGFloat a = [rgba[3] doubleValue];
  184. LookinColor *color = [LookinColor colorWithRed:r green:g blue:b alpha:a];
  185. return color;
  186. } else {
  187. NSAssert(NO, @"");
  188. return nil;
  189. }
  190. } else if (type == LookinCodingValueTypeImage) {
  191. if ([self isKindOfClass:[NSData class]]) {
  192. LookinImage *image = [[LookinImage alloc] initWithData:(NSData *)self];
  193. return image;
  194. } else {
  195. NSAssert(NO, @"");
  196. return nil;
  197. }
  198. } else {
  199. return self;
  200. }
  201. }
  202. @end