123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- #ifdef SHOULD_COMPILE_LOOKIN_SERVER
- //
- // LKS_CustomAttrGroupsMaker.m
- // LookinServer
- //
- // Created by LikaiMacStudioWork on 2023/10/31.
- //
- #import "LKS_CustomAttrGroupsMaker.h"
- #import "LKS_AttrGroupsMaker.h"
- #import "LookinAttributesGroup.h"
- #import "LookinAttributesSection.h"
- #import "LookinAttribute.h"
- #import "LookinDashboardBlueprint.h"
- #import "LookinIvarTrace.h"
- #import "UIColor+LookinServer.h"
- #import "LookinServerDefines.h"
- #import "LKS_CustomAttrSetterManager.h"
- @interface LKS_CustomAttrGroupsMaker ()
- /// key 是 section title
- @property(nonatomic, strong) NSMutableDictionary<NSString *, NSMutableArray<LookinAttribute *> *> *sectionAndAttrs;
- @property(nonatomic, copy) NSString *resolvedCustomDisplayTitle;
- @property(nonatomic, copy) NSString *resolvedDanceUISource;
- @property(nonatomic, strong) NSMutableArray *resolvedGroups;
- @property(nonatomic, weak) CALayer *layer;
- @end
- @implementation LKS_CustomAttrGroupsMaker
- - (instancetype)initWithLayer:(CALayer *)layer {
- if (self = [super init]) {
- self.sectionAndAttrs = [NSMutableDictionary dictionary];
- self.layer = layer;
- }
- return self;
- }
- - (void)execute {
- if (!self.layer) {
- NSAssert(NO, @"");
- return;
- }
- NSMutableArray<NSString *> *selectors = [NSMutableArray array];
- [selectors addObject:@"lookin_customDebugInfos"];
- for (int i = 0; i < 5; i++) {
- [selectors addObject:[NSString stringWithFormat:@"lookin_customDebugInfos_%@", @(i)]];
- }
-
- for (NSString *name in selectors) {
- [self makeAttrsForViewOrLayer:self.layer selectorName:name];
-
- UIView *view = self.layer.lks_hostView;
- if (view) {
- [self makeAttrsForViewOrLayer:view selectorName:name];
- }
- }
-
- if ([self.sectionAndAttrs count] == 0) {
- return;
- }
- NSMutableArray<LookinAttributesGroup *> *groups = [NSMutableArray array];
- [self.sectionAndAttrs enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull groupTitle, NSMutableArray<LookinAttribute *> * _Nonnull attrs, BOOL * _Nonnull stop) {
- LookinAttributesGroup *group = [LookinAttributesGroup new];
- group.userCustomTitle = groupTitle;
- group.identifier = LookinAttrGroup_UserCustom;
-
- NSMutableArray<LookinAttributesSection *> *sections = [NSMutableArray array];
- [attrs enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) {
- LookinAttributesSection *sec = [LookinAttributesSection new];
- sec.identifier = LookinAttrSec_UserCustom;
- sec.attributes = @[attr];
- [sections addObject:sec];
- }];
-
- group.attrSections = sections;
- [groups addObject:group];
- }];
- [groups sortedArrayUsingComparator:^NSComparisonResult(LookinAttributesGroup *obj1, LookinAttributesGroup *obj2) {
- return [obj1.userCustomTitle compare:obj2.userCustomTitle];
- }];
-
- self.resolvedGroups = groups;
- }
- - (void)makeAttrsForViewOrLayer:(id)viewOrLayer selectorName:(NSString *)selectorName {
- if (!viewOrLayer || !selectorName.length) {
- return;
- }
- if (![viewOrLayer isKindOfClass:[UIView class]] && ![viewOrLayer isKindOfClass:[CALayer class]]) {
- return;
- }
- SEL selector = NSSelectorFromString(selectorName);
- if (![viewOrLayer respondsToSelector:selector]) {
- return;
- }
- NSMethodSignature *signature = [viewOrLayer methodSignatureForSelector:selector];
- if (signature.numberOfArguments > 2) {
- NSAssert(NO, @"LookinServer - There should be no explicit parameters.");
- return;
- }
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
- [invocation setTarget:viewOrLayer];
- [invocation setSelector:selector];
- [invocation invoke];
-
- // 小心这里的内存管理
- NSDictionary<NSString *, id> * __unsafe_unretained tempRawData;
- [invocation getReturnValue:&tempRawData];
- if (!tempRawData || ![tempRawData isKindOfClass:[NSDictionary class]]) {
- return;
- }
-
- NSDictionary<NSString *, id> *rawData = tempRawData;
- NSArray *rawProperties = rawData[@"properties"];
-
- NSString *customTitle = rawData[@"title"];
- if (customTitle && [customTitle isKindOfClass:[NSString class]] && customTitle.length > 0) {
- self.resolvedCustomDisplayTitle = customTitle;
- }
-
- NSString *danceSource = rawData[@"lookin_source"];
- if (danceSource && [danceSource isKindOfClass:[NSString class]] && danceSource.length > 0) {
- self.resolvedDanceUISource = danceSource;
- }
-
- [self makeAttrsFromRawProperties:rawProperties];
- }
- - (void)makeAttrsFromRawProperties:(NSArray *)rawProperties {
- if (!rawProperties || ![rawProperties isKindOfClass:[NSArray class]]) {
- return;
- }
-
- for (NSDictionary<NSString *, id> *dict in rawProperties) {
- NSString *groupTitle;
- LookinAttribute *attr = [LKS_CustomAttrGroupsMaker attrFromRawDict:dict saveCustomSetter:YES groupTitle:&groupTitle];
- if (!attr) {
- continue;
- }
- if (!self.sectionAndAttrs[groupTitle]) {
- self.sectionAndAttrs[groupTitle] = [NSMutableArray array];
- }
- [self.sectionAndAttrs[groupTitle] addObject:attr];
- }
- }
- + (LookinAttribute *)attrFromRawDict:(NSDictionary *)dict saveCustomSetter:(BOOL)saveCustomSetter groupTitle:(inout NSString **)inoutGroupTitle {
- LookinAttribute *attr = [LookinAttribute new];
- attr.identifier = LookinAttr_UserCustom;
-
- NSString *title = dict[@"title"];
- NSString *type = dict[@"valueType"];
- NSString *section = dict[@"section"];
- id value = dict[@"value"];
-
- if (!title || ![title isKindOfClass:[NSString class]]) {
- NSLog(@"LookinServer - Wrong title");
- return nil;
- }
- if (!type || ![type isKindOfClass:[NSString class]]) {
- NSLog(@"LookinServer - Wrong valueType");
- return nil;
- }
- if (!section || ![section isKindOfClass:[NSString class]] || section.length == 0) {
- *inoutGroupTitle = @"Custom";
- } else {
- *inoutGroupTitle = section;
- }
-
- attr.displayTitle = title;
-
- NSString *fixedType = type.lowercaseString;
- if ([fixedType isEqualToString:@"string"]) {
- if (value != nil && ![value isKindOfClass:[NSString class]]) {
- // nil 是合法的
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeNSString;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_StringSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveStringSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"number"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSNumber class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeDouble;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_NumberSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveNumberSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"bool"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSNumber class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeBOOL;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_BoolSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveBoolSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"color"]) {
- if (value != nil && ![value isKindOfClass:[UIColor class]]) {
- // nil 是合法的
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeUIColor;
- attr.value = [(UIColor *)value lks_rgbaComponents];
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_ColorSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveColorSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"rect"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSValue class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeCGRect;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_RectSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveRectSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"size"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSValue class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeCGSize;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_SizeSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveSizeSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"point"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSValue class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeCGPoint;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_PointSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] savePointSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"insets"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSValue class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeUIEdgeInsets;
- attr.value = value;
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_InsetsSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveInsetsSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"shadow"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSDictionary class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- NSDictionary *shadowInfo = value;
- if (![shadowInfo[@"offset"] isKindOfClass:[NSValue class]]) {
- NSLog(@"LookinServer - Wrong value. No offset.");
- return nil;
- }
- if (![shadowInfo[@"opacity"] isKindOfClass:[NSNumber class]]) {
- NSLog(@"LookinServer - Wrong value. No opacity.");
- return nil;
- }
- if (![shadowInfo[@"radius"] isKindOfClass:[NSNumber class]]) {
- NSLog(@"LookinServer - Wrong value. No radius.");
- return nil;
- }
- NSMutableDictionary *checkedShadowInfo = [@{
- @"offset": shadowInfo[@"offset"],
- @"opacity": shadowInfo[@"opacity"],
- @"radius": shadowInfo[@"radius"]
- } mutableCopy];
- if ([shadowInfo[@"color"] isKindOfClass:[UIColor class]]) {
- checkedShadowInfo[@"color"] = [(UIColor *)shadowInfo[@"color"] lks_rgbaComponents];
- }
-
- attr.attrType = LookinAttrTypeShadow;
- attr.value = checkedShadowInfo;
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"enum"]) {
- if (value == nil) {
- NSLog(@"LookinServer - No value.");
- return nil;
- }
- if (![value isKindOfClass:[NSString class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeEnumString;
- attr.value = value;
-
- NSArray<NSString *> *allEnumCases = dict[@"allEnumCases"];
- if ([allEnumCases isKindOfClass:[NSArray class]]) {
- attr.extraValue = allEnumCases;
- }
-
- if (saveCustomSetter && dict[@"retainedSetter"]) {
- NSString *uniqueID = [[NSUUID new] UUIDString];
- LKS_EnumSetter setter = dict[@"retainedSetter"];
- [[LKS_CustomAttrSetterManager sharedInstance] saveEnumSetter:setter uniqueID:uniqueID];
- attr.customSetterID = uniqueID;
- }
-
- return attr;
- }
-
- if ([fixedType isEqualToString:@"json"]) {
- if (![value isKindOfClass:[NSString class]]) {
- NSLog(@"LookinServer - Wrong value type.");
- return nil;
- }
- attr.attrType = LookinAttrTypeJson;
- attr.value = value;
-
- return attr;
- }
-
- NSLog(@"LookinServer - Unsupported value type.");
- return nil;
- }
- - (NSArray<LookinAttributesGroup *> *)getGroups {
- return self.resolvedGroups;
- }
- - (NSString *)getCustomDisplayTitle {
- return self.resolvedCustomDisplayTitle;
- }
- - (NSString *)getDanceUISource {
- return self.resolvedDanceUISource;
- }
- + (NSArray<LookinAttributesGroup *> *)makeGroupsFromRawProperties:(NSArray *)rawProperties saveCustomSetter:(BOOL)saveCustomSetter {
- if (!rawProperties || ![rawProperties isKindOfClass:[NSArray class]]) {
- return nil;
- }
- // key 是 group title
- NSMutableDictionary<NSString *, NSMutableArray<LookinAttribute *> *> *groupTitleAndAttrs = [NSMutableDictionary dictionary];
-
- for (NSDictionary<NSString *, id> *dict in rawProperties) {
- NSString *groupTitle;
- LookinAttribute *attr = [LKS_CustomAttrGroupsMaker attrFromRawDict:dict saveCustomSetter:saveCustomSetter groupTitle:&groupTitle];
- if (!attr) {
- continue;
- }
- if (!groupTitleAndAttrs[groupTitle]) {
- groupTitleAndAttrs[groupTitle] = [NSMutableArray array];
- }
- [groupTitleAndAttrs[groupTitle] addObject:attr];
- }
-
- if ([groupTitleAndAttrs count] == 0) {
- return nil;
- }
- NSMutableArray<LookinAttributesGroup *> *groups = [NSMutableArray array];
- [groupTitleAndAttrs enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull groupTitle, NSMutableArray<LookinAttribute *> * _Nonnull attrs, BOOL * _Nonnull stop) {
- LookinAttributesGroup *group = [LookinAttributesGroup new];
- group.userCustomTitle = groupTitle;
- group.identifier = LookinAttrGroup_UserCustom;
-
- NSMutableArray<LookinAttributesSection *> *sections = [NSMutableArray array];
- [attrs enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) {
- LookinAttributesSection *sec = [LookinAttributesSection new];
- sec.identifier = LookinAttrSec_UserCustom;
- sec.attributes = @[attr];
- [sections addObject:sec];
- }];
-
- group.attrSections = sections;
- [groups addObject:group];
- }];
- [groups sortedArrayUsingComparator:^NSComparisonResult(LookinAttributesGroup *obj1, LookinAttributesGroup *obj2) {
- return [obj1.userCustomTitle compare:obj2.userCustomTitle];
- }];
- return [groups copy];
- }
- @end
- #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|