LKS_InbuiltAttrModificationHandler.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #ifdef SHOULD_COMPILE_LOOKIN_SERVER
  2. //
  3. // LKS_InbuiltAttrModificationHandler.m
  4. // LookinServer
  5. //
  6. // Created by Li Kai on 2019/6/12.
  7. // https://lookin.work
  8. //
  9. #import "LKS_InbuiltAttrModificationHandler.h"
  10. #import "UIColor+LookinServer.h"
  11. #import "LookinAttributeModification.h"
  12. #import "LKS_AttrGroupsMaker.h"
  13. #import "LookinDisplayItemDetail.h"
  14. #import "LookinStaticAsyncUpdateTask.h"
  15. #import "LookinServerDefines.h"
  16. #import "LKS_CustomAttrGroupsMaker.h"
  17. @implementation LKS_InbuiltAttrModificationHandler
  18. + (void)handleModification:(LookinAttributeModification *)modification completion:(void (^)(LookinDisplayItemDetail *data, NSError *error))completion {
  19. if (!completion) {
  20. NSAssert(NO, @"");
  21. return;
  22. }
  23. if (!modification || ![modification isKindOfClass:[LookinAttributeModification class]]) {
  24. completion(nil, LookinErr_Inner);
  25. return;
  26. }
  27. NSObject *receiver = [NSObject lks_objectWithOid:modification.targetOid];
  28. if (!receiver) {
  29. completion(nil, LookinErr_ObjNotFound);
  30. return;
  31. }
  32. NSMethodSignature *setterSignature = [receiver methodSignatureForSelector:modification.setterSelector];
  33. NSInvocation *setterInvocation = [NSInvocation invocationWithMethodSignature:setterSignature];
  34. setterInvocation.target = receiver;
  35. setterInvocation.selector = modification.setterSelector;
  36. if (setterSignature.numberOfArguments != 3 || ![receiver respondsToSelector:modification.setterSelector]) {
  37. completion(nil, LookinErr_Inner);
  38. return;
  39. }
  40. switch (modification.attrType) {
  41. case LookinAttrTypeNone:
  42. case LookinAttrTypeVoid: {
  43. completion(nil, LookinErr_Inner);
  44. return;
  45. }
  46. case LookinAttrTypeChar: {
  47. char expectedValue = [(NSNumber *)modification.value charValue];
  48. [setterInvocation setArgument:&expectedValue atIndex:2];
  49. break;
  50. }
  51. case LookinAttrTypeInt:
  52. case LookinAttrTypeEnumInt: {
  53. int expectedValue = [(NSNumber *)modification.value intValue];
  54. [setterInvocation setArgument:&expectedValue atIndex:2];
  55. break;
  56. }
  57. case LookinAttrTypeShort: {
  58. short expectedValue = [(NSNumber *)modification.value shortValue];
  59. [setterInvocation setArgument:&expectedValue atIndex:2];
  60. break;
  61. }
  62. case LookinAttrTypeLong:
  63. case LookinAttrTypeEnumLong: {
  64. long expectedValue = [(NSNumber *)modification.value longValue];
  65. [setterInvocation setArgument:&expectedValue atIndex:2];
  66. break;
  67. }
  68. case LookinAttrTypeLongLong: {
  69. long long expectedValue = [(NSNumber *)modification.value longLongValue];
  70. [setterInvocation setArgument:&expectedValue atIndex:2];
  71. break;
  72. }
  73. case LookinAttrTypeUnsignedChar: {
  74. unsigned char expectedValue = [(NSNumber *)modification.value unsignedCharValue];
  75. [setterInvocation setArgument:&expectedValue atIndex:2];
  76. break;
  77. }
  78. case LookinAttrTypeUnsignedInt: {
  79. unsigned int expectedValue = [(NSNumber *)modification.value unsignedIntValue];
  80. [setterInvocation setArgument:&expectedValue atIndex:2];
  81. break;
  82. }
  83. case LookinAttrTypeUnsignedShort: {
  84. unsigned short expectedValue = [(NSNumber *)modification.value unsignedShortValue];
  85. [setterInvocation setArgument:&expectedValue atIndex:2];
  86. break;
  87. }
  88. case LookinAttrTypeUnsignedLong: {
  89. unsigned long expectedValue = [(NSNumber *)modification.value unsignedLongValue];
  90. [setterInvocation setArgument:&expectedValue atIndex:2];
  91. break;
  92. }
  93. case LookinAttrTypeUnsignedLongLong: {
  94. unsigned long long expectedValue = [(NSNumber *)modification.value unsignedLongLongValue];
  95. [setterInvocation setArgument:&expectedValue atIndex:2];
  96. break;
  97. }
  98. case LookinAttrTypeFloat: {
  99. float expectedValue = [(NSNumber *)modification.value floatValue];
  100. [setterInvocation setArgument:&expectedValue atIndex:2];
  101. break;
  102. }
  103. case LookinAttrTypeDouble: {
  104. double expectedValue = [(NSNumber *)modification.value doubleValue];
  105. [setterInvocation setArgument:&expectedValue atIndex:2];
  106. break;
  107. }
  108. case LookinAttrTypeBOOL: {
  109. BOOL expectedValue = [(NSNumber *)modification.value boolValue];
  110. [setterInvocation setArgument:&expectedValue atIndex:2];
  111. break;
  112. }
  113. case LookinAttrTypeSel: {
  114. SEL expectedValue = NSSelectorFromString(modification.value);
  115. [setterInvocation setArgument:&expectedValue atIndex:2];
  116. break;
  117. }
  118. case LookinAttrTypeClass: {
  119. Class expectedValue = NSClassFromString(modification.value);
  120. [setterInvocation setArgument:&expectedValue atIndex:2];
  121. break;
  122. }
  123. case LookinAttrTypeCGPoint: {
  124. CGPoint expectedValue = [(NSValue *)modification.value CGPointValue];
  125. [setterInvocation setArgument:&expectedValue atIndex:2];
  126. break;
  127. }
  128. case LookinAttrTypeCGVector: {
  129. CGVector expectedValue = [(NSValue *)modification.value CGVectorValue];
  130. [setterInvocation setArgument:&expectedValue atIndex:2];
  131. break;
  132. }
  133. case LookinAttrTypeCGSize: {
  134. CGSize expectedValue = [(NSValue *)modification.value CGSizeValue];
  135. [setterInvocation setArgument:&expectedValue atIndex:2];
  136. break;
  137. }
  138. case LookinAttrTypeCGRect: {
  139. CGRect expectedValue = [(NSValue *)modification.value CGRectValue];
  140. [setterInvocation setArgument:&expectedValue atIndex:2];
  141. break;
  142. }
  143. case LookinAttrTypeCGAffineTransform: {
  144. CGAffineTransform expectedValue = [(NSValue *)modification.value CGAffineTransformValue];
  145. [setterInvocation setArgument:&expectedValue atIndex:2];
  146. break;
  147. }
  148. case LookinAttrTypeUIEdgeInsets: {
  149. UIEdgeInsets expectedValue = [(NSValue *)modification.value UIEdgeInsetsValue];
  150. [setterInvocation setArgument:&expectedValue atIndex:2];
  151. break;
  152. }
  153. case LookinAttrTypeUIOffset: {
  154. UIOffset expectedValue = [(NSValue *)modification.value UIOffsetValue];
  155. [setterInvocation setArgument:&expectedValue atIndex:2];
  156. break;
  157. }
  158. case LookinAttrTypeCustomObj:
  159. case LookinAttrTypeNSString: {
  160. NSObject *expectedValue = modification.value;
  161. [setterInvocation setArgument:&expectedValue atIndex:2];
  162. [setterInvocation retainArguments];
  163. break;
  164. }
  165. case LookinAttrTypeUIColor: {
  166. NSArray<NSNumber *> *rgba = modification.value;
  167. UIColor *expectedValue = [UIColor lks_colorFromRGBAComponents:rgba];
  168. [setterInvocation setArgument:&expectedValue atIndex:2];
  169. [setterInvocation retainArguments];
  170. break;
  171. }
  172. default: {
  173. completion(nil, LookinErr_Inner);
  174. return;
  175. }
  176. }
  177. NSError *error = nil;
  178. @try {
  179. [setterInvocation invoke];
  180. } @catch (NSException *exception) {
  181. NSString *errorMsg = [NSString stringWithFormat:LKS_Localized(@"<%@: %p>: an exception was raised when invoking %@. (%@)"), NSStringFromClass(receiver.class), receiver, NSStringFromSelector(modification.setterSelector), exception.reason];
  182. error = [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_Exception userInfo:@{NSLocalizedDescriptionKey:LKS_Localized(@"The modification may failed."), NSLocalizedRecoverySuggestionErrorKey:errorMsg}];
  183. } @finally {
  184. }
  185. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  186. CALayer *layer = nil;
  187. if ([receiver isKindOfClass:[CALayer class]]) {
  188. layer = (CALayer *)receiver;
  189. } else if ([receiver isKindOfClass:[UIView class]]) {
  190. layer = ((UIView *)receiver).layer;
  191. } else {
  192. completion(nil, LookinErr_ObjNotFound);
  193. return;
  194. }
  195. // 比如试图更改 frame 时,这个改动很有可能触发用户业务的 relayout,因此这时 dispatch 一下以确保拿到的 attrGroups 数据是最新的
  196. LookinDisplayItemDetail *detail = [LookinDisplayItemDetail new];
  197. detail.displayItemOid = modification.targetOid;
  198. detail.attributesGroupList = [LKS_AttrGroupsMaker attrGroupsForLayer:layer];
  199. NSString *version = modification.clientReadableVersion;
  200. if (version.length > 0 && [version lookin_numbericOSVersion] >= 10004) {
  201. LKS_CustomAttrGroupsMaker *maker = [[LKS_CustomAttrGroupsMaker alloc] initWithLayer:layer];
  202. [maker execute];
  203. detail.customAttrGroupList = [maker getGroups];
  204. }
  205. detail.frameValue = [NSValue valueWithCGRect:layer.frame];
  206. detail.boundsValue = [NSValue valueWithCGRect:layer.bounds];
  207. detail.hiddenValue = [NSNumber numberWithBool:layer.isHidden];
  208. detail.alphaValue = @(layer.opacity);
  209. completion(detail, error);
  210. });
  211. }
  212. + (void)handlePatchWithTasks:(NSArray<LookinStaticAsyncUpdateTask *> *)tasks block:(void (^)(LookinDisplayItemDetail *data))block {
  213. if (!block) {
  214. NSAssert(NO, @"");
  215. return;
  216. }
  217. [tasks enumerateObjectsUsingBlock:^(LookinStaticAsyncUpdateTask * _Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
  218. LookinDisplayItemDetail *itemDetail = [LookinDisplayItemDetail new];
  219. itemDetail.displayItemOid = task.oid;
  220. id object = [NSObject lks_objectWithOid:task.oid];
  221. if (!object || ![object isKindOfClass:[CALayer class]]) {
  222. block(itemDetail);
  223. return;
  224. }
  225. CALayer *layer = object;
  226. if (task.taskType == LookinStaticAsyncUpdateTaskTypeSoloScreenshot) {
  227. UIImage *image = [layer lks_soloScreenshotWithLowQuality:NO];
  228. itemDetail.soloScreenshot = image;
  229. } else if (task.taskType == LookinStaticAsyncUpdateTaskTypeGroupScreenshot) {
  230. UIImage *image = [layer lks_groupScreenshotWithLowQuality:NO];
  231. itemDetail.groupScreenshot = image;
  232. }
  233. block(itemDetail);
  234. }];
  235. }
  236. @end
  237. #endif /* SHOULD_COMPILE_LOOKIN_SERVER */