diff --git a/CHANGELOG.md b/CHANGELOG.md index f0d1bc3e..f4dfbece 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [1.3.4](https://github.com/HDB-Li/LLDebugTool/releases/tag/1.3.4) (10/31/2019) + +### More practical `Hierarchy` function + +Now you can use the `Hierarchy` function to dynamically modify attribute values. There are common attributes in the shortcut interface and most attributes in the details interface. It's a very interesting and useful function. + +#### Update + +* Update `Hierarchy Detail` to dynamic modify properties. + ## [1.3.3](https://github.com/HDB-Li/LLDebugTool/releases/tag/1.3.3) (10/18/2019) ### Add `Html` function. diff --git a/LLDebugTool.podspec b/LLDebugTool.podspec index 8a3b4c00..7e971931 100644 --- a/LLDebugTool.podspec +++ b/LLDebugTool.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LLDebugTool" - s.version = "1.3.3" + s.version = "1.3.4" s.summary = "LLDebugTool is a debugging tool for developers and testers that can help you analyze and manipulate data in non-xcode situations." s.homepage = "https://github.com/HDB-Li/LLDebugTool" s.license = "MIT" @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.public_header_files = "LLDebugTool/LLDebug.h", "LLDebugTool/DebugTool/*.h" s.source_files = "LLDebugTool/**/*.{h,m}" s.resources = "LLDebugTool/**/*.{xib,storyboard,bundle}" - s.frameworks = "Foundation", "UIKit", "Photos", "SystemConfiguration", "CoreTelephony", "QuickLook" + s.frameworks = "Foundation", "UIKit", "Photos", "SystemConfiguration", "CoreTelephony", "QuickLook", "WebKit" s.dependency "FMDB", "~> 2.0" s.dependency "Masonry" diff --git a/LLDebugTool/Core/Component/Crash/UserInterface/LLCrashViewController.m b/LLDebugTool/Core/Component/Crash/UserInterface/LLCrashViewController.m index 0e99dd93..71656128 100644 --- a/LLDebugTool/Core/Component/Crash/UserInterface/LLCrashViewController.m +++ b/LLDebugTool/Core/Component/Crash/UserInterface/LLCrashViewController.m @@ -30,6 +30,7 @@ #import "LLCrashDetailViewController.h" #import "LLImageNameConfig.h" #import "LLToastUtils.h" +#import "UIViewController+LL_Utils.h" static NSString *const kCrashCellID = @"CrashCellID"; @@ -87,7 +88,7 @@ - (void)deleteFilesWithIndexPaths:(NSArray *)indexPaths { [weakSelf.searchDataArray removeObjectsInArray:models]; [weakSelf.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; } else { - [weakSelf showAlertControllerWithMessage:@"Remove crash model fail" handler:^(NSInteger action) { + [weakSelf LL_showAlertControllerWithMessage:@"Remove crash model fail" handler:^(NSInteger action) { if (action == 1) { [weakSelf loadData]; } diff --git a/LLDebugTool/Core/Component/Function/UserInterface/LLFunctionItemContainerView.m b/LLDebugTool/Core/Component/Function/UserInterface/LLFunctionItemContainerView.m index 825b2136..a53081c9 100644 --- a/LLDebugTool/Core/Component/Function/UserInterface/LLFunctionItemContainerView.m +++ b/LLDebugTool/Core/Component/Function/UserInterface/LLFunctionItemContainerView.m @@ -90,7 +90,7 @@ - (void)updateUI:(NSArray *)dataArray { for (int i = 0; i < dataArray.count; i++) { LLFunctionItemModel *model = dataArray[i]; LLFunctionItemView *itemView = [[LLFunctionItemView alloc] initWithFrame:CGRectZero]; - [itemView LL_AddClickListener:self action:@selector(itemViewClicked:)]; + [itemView LL_addClickListener:self action:@selector(itemViewClicked:)]; itemView.model = model; [self addSubview:itemView]; [self.itemViews addObject:itemView]; diff --git a/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.h b/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.h index 7afe25bd..383b1457 100644 --- a/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.h +++ b/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.h @@ -25,12 +25,28 @@ #import #import "LLTitleCellCategoryModel.h" +FOUNDATION_EXPORT NSNotificationName _Nonnull const LLHierarchyChangeNotificationName; + NS_ASSUME_NONNULL_BEGIN @interface NSObject (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels; +- (void)LL_showIntAlertAndAutomicSetWithKeyPath:(NSString *)keyPath; + +- (void)LL_showFrameAlertAndAutomicSetWithKeyPath:(NSString *)keyPath; + +- (void)LL_showColorAlertAndAutomicSetWithKeyPath:(NSString *)keyPath; + +- (void)LL_showFontAlertAndAutomicSetWithKeyPath:(NSString *)keyPath; + +@end + +@interface UIView (LL_Hierarchy) + +- (NSArray *)LL_sizeHierarchyCategoryModels; + @end NS_ASSUME_NONNULL_END diff --git a/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.m b/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.m index 1c064b7f..a8cb2afa 100644 --- a/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.m +++ b/LLDebugTool/Core/Component/Hierarchy/Function/NSObject+LL_Hierarchy.m @@ -27,6 +27,11 @@ #import "UIColor+LL_Utils.h" #import "LLFormatterTool.h" #import "LLEnumDescription.h" +#import "LLTool.h" +#import "UIViewController+LL_Utils.h" +#import "UIColor+LL_Utils.h" + +NSNotificationName const LLHierarchyChangeNotificationName = @"LLHierarchyChangeNotificationName"; @implementation NSObject (LL_Hierarchy) @@ -34,32 +39,18 @@ @implementation NSObject (LL_Hierarchy) NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Class Name" detailTitle:NSStringFromClass(self.class)]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Class Name" detailTitle:NSStringFromClass(self.class)] noneInsets]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Address" detailTitle:[NSString stringWithFormat:@"%p",self]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Address" detailTitle:[NSString stringWithFormat:@"%p",self]] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Description" detailTitle:self.description]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Description" detailTitle:self.description] noneInsets]; [settings addObject:model3]; return @[[[LLTitleCellCategoryModel alloc] initWithTitle:@"Object" items:settings]]; } -- (LLTitleCellModel *)LL_normalInsetsCellModelWithTitle:(NSString *)title detailTitle:(NSString *)detailTitle { - return [self LL_cellModelWithTitle:title detailTitle:detailTitle insets:UIEdgeInsetsMake(0, kLLGeneralMargin, 0, 0)]; -} - -- (LLTitleCellModel *)LL_noneInsetsCellModelWithTitle:(NSString *)title detailTitle:(NSString *)detailTitle { - return [self LL_cellModelWithTitle:title detailTitle:detailTitle insets:UIEdgeInsetsMake(0, LL_SCREEN_WIDTH, 0, 0)]; -} - -- (LLTitleCellModel *)LL_cellModelWithTitle:(NSString *)title detailTitle:(NSString *)detailTitle insets:(UIEdgeInsets)insets { - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:title detailTitle:detailTitle]; - model.separatorInsets = insets; - return model; -} - - (NSString *)LL_hierarchyColorDescription:(UIColor *_Nullable)color { if (!color) { return @""; @@ -70,7 +61,16 @@ - (NSString *)LL_hierarchyColorDescription:(UIColor *_Nullable)color { NSString *colorName = [color LL_systemColorName]; - return colorName ? [rgb stringByAppendingFormat:@"\n%@",colorName] : rgb; + return colorName ? [rgb stringByAppendingFormat:@"\n%@",colorName] : [rgb stringByAppendingFormat:@"\n%@",[color LL_HexString]]; +} + +- (UIColor *)LL_colorFromString:(NSString *)string originalColor:(UIColor *)color { + BOOL error = NO; + UIColor *newColor = [UIColor LL_colorWithHex:string error:&error]; + if (error) { + return color; + } + return newColor; } - (NSString *)LL_hierarchyBoolDescription:(BOOL)flag { @@ -92,6 +92,13 @@ - (NSString *)LL_hierarchyObjectDescription:(NSObject *)obj { return text; } +- (NSString *)LL_hierarchyDateDescription:(NSDate *)date { + if (!date) { + return @""; + } + return [LLFormatterTool stringFromDate:date style:FormatterToolDateStyle3] ?: @""; +} + - (NSString *)LL_hierarchyTextDescription:(NSString *)text { if (text == nil) { return @""; @@ -102,14 +109,53 @@ - (NSString *)LL_hierarchyTextDescription:(NSString *)text { return text; } +- (NSString *)LL_hierarchyPointDescription:(CGPoint)point { + return [NSString stringWithFormat:@"X: %@ Y: %@",[LLFormatterTool formatNumber:@(point.x)],[LLFormatterTool formatNumber:@(point.y)]]; +} + +- (CGPoint)LL_pointFromString:(NSString *)string orginalPoint:(CGPoint)point { + CGPoint newPoint = CGPointFromString(string); + return newPoint; +} + - (NSString *)LL_hierarchySizeDescription:(CGSize)size { - return [NSString stringWithFormat:@"w %@ h %@",[LLFormatterTool formatNumber:@(size.width)], [LLFormatterTool formatNumber:@(size.height)]]; + return [NSString stringWithFormat:@"W: %@ H: %@",[LLFormatterTool formatNumber:@(size.width)], [LLFormatterTool formatNumber:@(size.height)]]; +} + +- (CGRect)LL_rectFromString:(NSString *)string originalRect:(CGRect)rect { + CGRect newRect = CGRectFromString(string); + if (CGRectEqualToRect(newRect, CGRectZero) && ![string isEqualToString:NSStringFromCGRect(CGRectZero)]) { + // Wrong text. + [LLTool log:@"Input a wrong rect string."]; + return rect; + } + return newRect; +} + +- (CGSize)LL_sizeFromString:(NSString *)string originalSize:(CGSize)size { + CGSize newSize = CGSizeFromString(string); + if (CGSizeEqualToSize(newSize, CGSizeZero) && ![string isEqualToString:NSStringFromCGSize(CGSizeZero)]) { + // Wrong text. + [LLTool log:@"Input a wrong size string."]; + return size; + } + return newSize; } - (NSString *)LL_hierarchyInsetsTopBottomDescription:(UIEdgeInsets)insets { return [NSString stringWithFormat:@"top %@ bottom %@",[LLFormatterTool formatNumber:@(insets.top)], [LLFormatterTool formatNumber:@(insets.bottom)]]; } +- (UIEdgeInsets)LL_insetsFromString:(NSString *)string originalInsets:(UIEdgeInsets)insets { + UIEdgeInsets newInsets = UIEdgeInsetsFromString(string); + if (UIEdgeInsetsEqualToEdgeInsets(newInsets, UIEdgeInsetsZero) && ![string isEqualToString:NSStringFromUIEdgeInsets(UIEdgeInsetsZero)]) { + // Wrong text. + [LLTool log:@"Input a wrong insets string."]; + return insets; + } + return newInsets; +} + - (NSString *)LL_hierarchyInsetsLeftRightDescription:(UIEdgeInsets)insets { return [NSString stringWithFormat:@"left %@ right %@",[LLFormatterTool formatNumber:@(insets.left)], [LLFormatterTool formatNumber:@(insets.right)]]; } @@ -118,71 +164,245 @@ - (NSString *)LL_hierarchyOffsetDescription:(UIOffset)offset { return [NSString stringWithFormat:@"h %@ v %@",[LLFormatterTool formatNumber:@(offset.horizontal)], [LLFormatterTool formatNumber:@(offset.vertical)]]; } +- (void)LL_showIntAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[NSString stringWithFormat:@"%@",[self valueForKeyPath:keyPath]] handler:^(NSString * _Nullable newText) { + [weakSelf setValue:@([newText integerValue]) forKeyPath:keyPath]; + }]; +} + +- (void)LL_showDoubleAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[LLFormatterTool formatNumber:[self valueForKeyPath:keyPath]] handler:^(NSString * _Nullable newText) { + [weakSelf setValue:@([newText doubleValue]) forKeyPath:keyPath]; + }]; +} + +- (void)LL_showColorAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block UIColor *color = [self valueForKeyPath:keyPath]; + if (color && ![color isKindOfClass:[UIColor class]]) { + return; + } + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[color LL_HexString] handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[weakSelf LL_colorFromString:newText originalColor:color] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showFrameAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block NSValue *value = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:NSStringFromCGRect([value CGRectValue]) handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[NSValue valueWithCGRect:[weakSelf LL_rectFromString:newText originalRect:[value CGRectValue]]] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showPointAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block NSValue *value = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:NSStringFromCGPoint([value CGPointValue]) handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[NSValue valueWithCGPoint:[weakSelf LL_pointFromString:newText orginalPoint:[value CGPointValue]]] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showEdgeInsetsAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block NSValue *value = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:NSStringFromUIEdgeInsets([value UIEdgeInsetsValue]) handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[NSValue valueWithUIEdgeInsets:[weakSelf LL_insetsFromString:newText originalInsets:[value UIEdgeInsetsValue]]] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showTextAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[self valueForKeyPath:keyPath] handler:^(NSString * _Nullable newText) { + [weakSelf setValue:newText forKeyPath:keyPath]; + }]; +} + +- (void)LL_showAttributeTextAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block NSAttributedString *attribute = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:attribute.string handler:^(NSString * _Nullable newText) { + NSMutableAttributedString *mutAttribute = [[NSMutableAttributedString alloc] initWithAttributedString:attribute]; + [mutAttribute replaceCharactersInRange:NSMakeRange(0, attribute.string.length) withString:newText]; + [weakSelf setValue:[mutAttribute copy] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showSizeAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block NSValue *value = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:NSStringFromCGSize([value CGSizeValue]) handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[NSValue valueWithCGSize:[weakSelf LL_sizeFromString:newText originalSize:[value CGSizeValue]]] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showFontAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + __block UIFont *font = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[LLFormatterTool formatNumber:@(font.pointSize)] handler:^(NSString * _Nullable newText) { + [weakSelf setValue:[font fontWithSize:[newText doubleValue]] forKeyPath:keyPath]; + }]; +} + +- (void)LL_showDateAlertAndAutomicSetWithKeyPath:(NSString *)keyPath { + NSDate *date = [self valueForKeyPath:keyPath]; + __weak typeof(self) weakSelf = self; + [self LL_showTextFieldAlertWithText:[LLFormatterTool stringFromDate:date style:FormatterToolDateStyle3] handler:^(NSString * _Nullable newText) { + NSDate *newDate = [LLFormatterTool dateFromString:newText style:FormatterToolDateStyle3]; + if (newDate) { + [weakSelf setValue:newDate forKeyPath:keyPath]; + } + }]; +} + +- (void)LL_showTextFieldAlertWithText:(NSString *)text handler:(nullable void (^)(NSString * _Nullable newText))handler { + [[LLTool keyWindow].rootViewController.LL_currentShowingViewController LL_showTextFieldAlertControllerWithMessage:@"Change Property" text:text handler:^(NSString * _Nullable newText) { + if (handler) { + handler(newText); + } + [self LL_postHierarchyChangeNotification]; + }]; +} + +- (void)LL_showActionSheetWithActions:(NSArray *)actions currentAction:(NSString *)currentAction completion:(void (^)(NSInteger index))completion { + [[LLTool keyWindow].rootViewController.LL_currentShowingViewController LL_showActionSheetWithTitle:@"Change Property" actions:actions currentAction:currentAction completion:^(NSInteger index) { + if (completion) { + completion(index); + } + [self LL_postHierarchyChangeNotification]; + }]; +} + +- (void)LL_postHierarchyChangeNotification { + [[NSNotificationCenter defaultCenter] postNotificationName:LLHierarchyChangeNotificationName object:self]; +} + +- (void)LL_replaceAttributeString:(NSString *)newString key:(NSString *)key { + NSAttributedString *string = [self valueForKey:key]; + if (string && ![string isKindOfClass:[NSAttributedString class]]) { + [LLTool log:[NSString stringWithFormat:@"KeyPath:%@ isn't a NSAttributedString or nil", key]]; + return; + } + NSMutableAttributedString *attribute = string ? [[NSMutableAttributedString alloc] initWithAttributedString:string] : [[NSMutableAttributedString alloc] init]; + [attribute replaceCharactersInRange:NSMakeRange(0, string.length) withString:newString]; + [self setValue:string forKey:key]; +} + @end @implementation UIView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Layer" detailTitle:self.layer.description]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Layer" detailTitle:self.layer.description] noneInsets]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Layer Class" detailTitle:NSStringFromClass(self.layer.class)]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Layer Class" detailTitle:NSStringFromClass(self.layer.class)]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Content Model" detailTitle:[LLEnumDescription viewContentModeDescription:self.contentMode]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Content Model" detailTitle:[LLEnumDescription viewContentModeDescription:self.contentMode]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription viewContentModeDescriptions] currentAction:[LLEnumDescription viewContentModeDescription:weakSelf.contentMode] completion:^(NSInteger index) { + weakSelf.contentMode = index; + }]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:@"Tag" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.tag]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:@"Tag" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.tag]]; + model4.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"tag"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Interaction" detailTitle:[NSString stringWithFormat:@"User Interaction Enabled %@",[self LL_hierarchyBoolDescription:self.isUserInteractionEnabled]]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"User Interaction" flag: self.isUserInteractionEnabled] noneInsets]; + model5.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.userInteractionEnabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Multiple Touch %@", [self LL_hierarchyBoolDescription:self.isMultipleTouchEnabled]]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Multiple Touch" flag:self.isMultipleTouchEnabled]; + model6.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.multipleTouchEnabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Alpha" detailTitle:[LLFormatterTool formatNumber:@(self.alpha)]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Alpha" detailTitle:[LLFormatterTool formatNumber:@(self.alpha)]] noneInsets]; + model7.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"alpha"]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Background" detailTitle:[self LL_hierarchyColorDescription:self.backgroundColor]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Background" detailTitle:[self LL_hierarchyColorDescription:self.backgroundColor]] noneInsets]; + model8.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"backgroundColor"]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Tint" detailTitle:[self LL_hierarchyColorDescription:self.tintColor]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Tint" detailTitle:[self LL_hierarchyColorDescription:self.tintColor]]; + model9.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"tintColor"]; + }; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Drawing" detailTitle:[NSString stringWithFormat:@"Opaque %@",[self LL_hierarchyBoolDescription:self.isOpaque]]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Drawing" detailTitle:@"Opaque" flag:self.isOpaque] noneInsets]; + model10.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.opaque = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Hidden %@",[self LL_hierarchyBoolDescription:self.isHidden]]]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Hidden" flag:self.isHidden] noneInsets]; + model11.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.hidden = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Clears Graphics Context %@",[self LL_hierarchyBoolDescription:self.clearsContextBeforeDrawing]]]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Clears Graphics Context" flag:self.clearsContextBeforeDrawing] noneInsets]; + model12.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.clearsContextBeforeDrawing = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Clip To Bounds %@",[self LL_hierarchyBoolDescription:self.clipsToBounds]]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Clip To Bounds" flag:self.clipsToBounds] noneInsets]; + model13.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.clipsToBounds = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Autoresizes Subviews %@", [self LL_hierarchyBoolDescription:self.autoresizesSubviews]]]; + LLTitleCellModel *model14 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Autoresizes Subviews" flag:self.autoresizesSubviews]; + model14.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.autoresizesSubviews = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_noneInsetsCellModelWithTitle:@"Trait Collection" detailTitle:nil]; + LLTitleCellModel *model15 = [[[LLTitleCellModel alloc] initWithTitle:@"Trait Collection" detailTitle:nil] noneInsets]; [settings addObject:model15]; if (@available(iOS 12.0, *)) { - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[LLEnumDescription userInterfaceStyleDescription:self.traitCollection.userInterfaceStyle]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[LLEnumDescription userInterfaceStyleDescription:self.traitCollection.userInterfaceStyle]] noneInsets]; [settings addObject:model16]; } - LLTitleCellModel *model17 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[@"Vertical" stringByAppendingFormat:@" %@",[LLEnumDescription userInterfaceSizeClassDescription:self.traitCollection.verticalSizeClass]]]; + LLTitleCellModel *model17 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[@"Vertical" stringByAppendingFormat:@" %@",[LLEnumDescription userInterfaceSizeClassDescription:self.traitCollection.verticalSizeClass]]] noneInsets]; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[@"Horizontal" stringByAppendingFormat:@" %@",[LLEnumDescription userInterfaceSizeClassDescription:self.traitCollection.horizontalSizeClass]]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[@"Horizontal" stringByAppendingFormat:@" %@",[LLEnumDescription userInterfaceSizeClassDescription:self.traitCollection.horizontalSizeClass]]] noneInsets]; [settings addObject:model18]; if (@available(iOS 10.0, *)) { - LLTitleCellModel *model19 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[LLEnumDescription traitEnvironmentLayoutDirectionDescription:self.traitCollection.layoutDirection]]; + LLTitleCellModel *model19 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[LLEnumDescription traitEnvironmentLayoutDirectionDescription:self.traitCollection.layoutDirection]]; [settings addObject:model19]; } @@ -197,53 +417,238 @@ @implementation UIView (LL_Hierarchy) return [models copy]; } +- (NSArray *)LL_sizeHierarchyCategoryModels { + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; + + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Frame" detailTitle:[self LL_hierarchyPointDescription:self.frame.origin]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showFrameAlertAndAutomicSetWithKeyPath:@"frame"]; + }; + [settings addObject:model1]; + + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchySizeDescription:self.frame.size]] noneInsets]; + [settings addObject:model2]; + + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Bounds" detailTitle:[self LL_hierarchyPointDescription:self.bounds.origin]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showFrameAlertAndAutomicSetWithKeyPath:@"bounds"]; + }; + [settings addObject:model3]; + + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchySizeDescription:self.bounds.size]] noneInsets]; + [settings addObject:model4]; + + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Center" detailTitle:[self LL_hierarchyPointDescription:self.center]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showPointAlertAndAutomicSetWithKeyPath:@"center"]; + }; + [settings addObject:model5]; + + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Position" detailTitle:[self LL_hierarchyPointDescription:self.layer.position]] noneInsets]; + model6.block = ^{ + [weakSelf LL_showPointAlertAndAutomicSetWithKeyPath:@"layer.position"]; + }; + [settings addObject:model6]; + + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:@"Z Position" detailTitle:[LLFormatterTool formatNumber:@(self.layer.zPosition)]]; + model7.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"layer.zPosition"]; + }; + [settings addObject:model7]; + + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Anchor Point" detailTitle:[self LL_hierarchyPointDescription:self.layer.anchorPoint]] noneInsets]; + model8.block = ^{ + [weakSelf LL_showPointAlertAndAutomicSetWithKeyPath:@"layer.anchorPoint"]; + }; + [settings addObject:model8]; + + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Anchor Point Z" detailTitle:[LLFormatterTool formatNumber:@(self.layer.anchorPointZ)]]; + model9.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"layer.anchorPointZ"]; + }; + [settings addObject:model9]; + + LLTitleCellModel *lastConstrainModel = nil; + + for (NSLayoutConstraint *constrain in self.constraints) { + if (!constrain.shouldBeArchived) { + continue; + } + NSString *constrainDesc = [self LL_hierarchyLayoutConstraintDescription:constrain]; + if (constrainDesc) { + LLTitleCellModel *mod = [[[LLTitleCellModel alloc] initWithTitle:lastConstrainModel ? nil : @"Constrains" detailTitle:constrainDesc] noneInsets]; + __weak NSLayoutConstraint *cons = constrain; + mod.block = ^{ + [weakSelf LL_showTextFieldAlertWithText:[LLFormatterTool formatNumber:@(cons.constant)] handler:^(NSString * _Nullable newText) { + cons.constant = [newText doubleValue]; + [weakSelf setNeedsLayout]; + }]; + }; + [settings addObject:mod]; + lastConstrainModel = mod; + } + } + + for (NSLayoutConstraint *constrain in self.superview.constraints) { + if (!constrain.shouldBeArchived) { + continue; + } + if (constrain.firstItem == self || constrain.secondItem == self) { + NSString *constrainDesc = [self LL_hierarchyLayoutConstraintDescription:constrain]; + if (constrainDesc) { + LLTitleCellModel *mod = [[[LLTitleCellModel alloc] initWithTitle:lastConstrainModel ? nil : @"Constrains" detailTitle:constrainDesc] noneInsets]; + __weak NSLayoutConstraint *cons = constrain; + mod.block = ^{ + [weakSelf LL_showTextFieldAlertWithText:[LLFormatterTool formatNumber:@(cons.constant)] handler:^(NSString * _Nullable newText) { + cons.constant = [newText doubleValue]; + [weakSelf setNeedsLayout]; + }]; + }; + [settings addObject:mod]; + lastConstrainModel = mod; + } + } + } + + [lastConstrainModel normalInsets]; + + return @[[[LLTitleCellCategoryModel alloc] initWithTitle:@"View" items:settings]]; +} + +- (NSString *)LL_hierarchyLayoutConstraintDescription:(NSLayoutConstraint *)constraint { + NSMutableString *string = [[NSMutableString alloc] init]; + if (constraint.firstItem == self) { + [string appendString:@"self."]; + } else if (constraint.firstItem == self.superview) { + [string appendString:@"superview."]; + } else { + [string appendFormat:@"%@.",NSStringFromClass([constraint.firstItem class])]; + } + [string appendString:[LLEnumDescription layoutAttributeDescription:constraint.firstAttribute]]; + [string appendString:[LLEnumDescription layoutRelationDescription:constraint.relation]]; + if (constraint.secondItem) { + if (constraint.secondItem == self) { + [string appendString:@"self."]; + } else if (constraint.secondItem == self.superview) { + [string appendString:@"superview."]; + } else { + [string appendFormat:@"%@.",NSStringFromClass([constraint.secondItem class])]; + } + [string appendString:[LLEnumDescription layoutAttributeDescription:constraint.secondAttribute]]; + if (constraint.multiplier != 1) { + [string appendFormat:@" * %@",[LLFormatterTool formatNumber:@(constraint.multiplier)]]; + } + if (constraint.constant > 0) { + [string appendFormat:@" + %@",[LLFormatterTool formatNumber:@(constraint.constant)]]; + } else if (constraint.constant < 0) { + [string appendFormat:@" - %@",[LLFormatterTool formatNumber:@(fabs(constraint.constant))]]; + } + } else if (constraint.constant) { + [string appendString:[LLFormatterTool formatNumber:@(constraint.constant)]]; + } else { + return nil; + } + + [string appendFormat:@" @ %@",[LLFormatterTool formatNumber:@(constraint.priority)]]; + return string; +} + @end @implementation UILabel (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Text" detailTitle:[self LL_hierarchyTextDescription:self.text]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Text" detailTitle:[self LL_hierarchyTextDescription:self.text]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"text"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:self.attributedText == nil ? @"Plain Text" : @"Attributed Text"]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.attributedText == nil ? @"Plain Text" : @"Attributed Text"] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Text" detailTitle:[self LL_hierarchyColorDescription:self.textColor]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Text" detailTitle:[self LL_hierarchyColorDescription:self.textColor]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"textColor"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyObjectDescription:self.font]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyObjectDescription:self.font]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showFontAlertAndAutomicSetWithKeyPath:@"font"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Aligned %@", [LLEnumDescription textAlignmentDescription:self.textAlignment]]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[NSString stringWithFormat:@"Aligned %@", [LLEnumDescription textAlignmentDescription:self.textAlignment]]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAlignments] currentAction:[LLEnumDescription textAlignmentDescription:weakSelf.textAlignment] completion:^(NSInteger index) { + weakSelf.textAlignment = index; + }]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:@"Lines" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfLines]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Lines" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfLines]] noneInsets]; + model6.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"numberOfLines"]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:[NSString stringWithFormat:@"Enabled %@",[self LL_hierarchyBoolDescription:self.isEnabled]]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:@"Enabled" flag:self.isEnabled] noneInsets]; + model7.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.enabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Highlighted %@", [self LL_hierarchyBoolDescription:self.isHighlighted]]]; + LLTitleCellModel *model8 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Highlighted" flag:self.isHighlighted]; + model8.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.highlighted = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_noneInsetsCellModelWithTitle:@"Baseline" detailTitle:[NSString stringWithFormat:@"Align %@",[LLEnumDescription baselineAdjustmentDescription:self.baselineAdjustment]]]; + LLTitleCellModel *model9 = [[[LLTitleCellModel alloc] initWithTitle:@"Baseline" detailTitle:[NSString stringWithFormat:@"Align %@",[LLEnumDescription baselineAdjustmentDescription:self.baselineAdjustment]]] noneInsets]; + model9.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription baselineAdjustments] currentAction:[LLEnumDescription baselineAdjustmentDescription:weakSelf.baselineAdjustment] completion:^(NSInteger index) { + weakSelf.baselineAdjustment = index; + }]; + }; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Line Break" detailTitle:[LLEnumDescription lineBreakModeDescription:self.lineBreakMode]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Line Break" detailTitle:[LLEnumDescription lineBreakModeDescription:self.lineBreakMode]] noneInsets]; + model10.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription lineBreaks] currentAction:[LLEnumDescription lineBreakModeDescription:weakSelf.lineBreakMode] completion:^(NSInteger index) { + weakSelf.lineBreakMode = index; + }]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_normalInsetsCellModelWithTitle:@"Min Font Scale" detailTitle:[LLFormatterTool formatNumber:@(self.minimumScaleFactor)]]; + LLTitleCellModel *model11 = [[LLTitleCellModel alloc] initWithTitle:@"Min Font Scale" detailTitle:[LLFormatterTool formatNumber:@(self.minimumScaleFactor)]]; + model11.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"minimumScaleFactor"]; + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:@"Highlighted" detailTitle:[self LL_hierarchyColorDescription:self.highlightedTextColor]]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:@"Highlighted" detailTitle:[self LL_hierarchyColorDescription:self.highlightedTextColor]] noneInsets]; + model12.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"highlightedTextColor"]; + }; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:self.shadowColor]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:self.shadowColor]] noneInsets]; + model13.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"shadowColor"]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_normalInsetsCellModelWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:self.shadowOffset]]; + LLTitleCellModel *model14 = [[LLTitleCellModel alloc] initWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:self.shadowOffset]]; + model14.block = ^{ + [weakSelf LL_showSizeAlertAndAutomicSetWithKeyPath:@"shadowOffset"]; + }; [settings addObject:model14]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Label" items:settings]; @@ -262,21 +667,45 @@ @implementation UILabel (LL_Hierarchy) @implementation UIControl (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Alignment" detailTitle:[NSString stringWithFormat:@"%@ Horizonally", [LLEnumDescription controlContentHorizontalAlignmentDescription:self.contentHorizontalAlignment]]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Alignment" detailTitle:[NSString stringWithFormat:@"%@ Horizonally", [LLEnumDescription controlContentHorizontalAlignmentDescription:self.contentHorizontalAlignment]]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription controlContentHorizontalAlignments] currentAction:[LLEnumDescription controlContentHorizontalAlignmentDescription:weakSelf.contentHorizontalAlignment] completion:^(NSInteger index) { + weakSelf.contentHorizontalAlignment = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"%@ Vertically", [LLEnumDescription controlContentVerticalAlignmentDescription:self.contentVerticalAlignment]]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[NSString stringWithFormat:@"%@ Vertically", [LLEnumDescription controlContentVerticalAlignmentDescription:self.contentVerticalAlignment]]]; + model2.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription controlContentVerticalAlignments] currentAction:[LLEnumDescription controlContentVerticalAlignmentDescription:weakSelf.contentVerticalAlignment] completion:^(NSInteger index) { + weakSelf.contentVerticalAlignment = index; + }]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Content" detailTitle:self.isSelected ? @"Selected" : @"Not Selected"]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Content" detailTitle:self.isSelected ? @"Selected" : @"Not Selected" flag:self.isSelected] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.selected = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:self.isEnabled ? @"Enabled" : @"Not Enabled"]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.isEnabled ? @"Enabled" : @"Not Enabled" flag:self.isEnabled] noneInsets]; + model4.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.enabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:self.isHighlighted ? @"Highlighted" : @"Not Highlighted"]; + LLTitleCellModel *model5 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.isHighlighted ? @"Highlighted" : @"Not Highlighted" flag:self.isHighlighted]; + model5.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.highlighted = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model5]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Control" items:settings]; @@ -295,76 +724,106 @@ @implementation UIControl (LL_Hierarchy) @implementation UIButton (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Type" detailTitle:[LLEnumDescription buttonTypeDescription:self.buttonType]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Type" detailTitle:[LLEnumDescription buttonTypeDescription:self.buttonType]]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"State" detailTitle:[LLEnumDescription controlStateDescription:self.state]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"State" detailTitle:[LLEnumDescription controlStateDescription:self.state]] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Title" detailTitle:[self LL_hierarchyTextDescription:self.currentTitle]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Title" detailTitle:[self LL_hierarchyTextDescription:self.currentTitle]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showTextFieldAlertWithText:weakSelf.currentTitle handler:^(NSString * _Nullable newText) { + [weakSelf setTitle:newText forState:weakSelf.state]; + }]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:self.currentAttributedTitle == nil ? @"Plain Text" : @"Attributed Text"]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.currentAttributedTitle == nil ? @"Plain Text" : @"Attributed Text"] noneInsets]; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Text Color" detailTitle:[self LL_hierarchyColorDescription:self.currentTitleColor]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Text Color" detailTitle:[self LL_hierarchyColorDescription:self.currentTitleColor]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showTextFieldAlertWithText:[weakSelf.currentTitleColor LL_HexString] handler:^(NSString * _Nullable newText) { + [weakSelf setTitleColor:[weakSelf LL_colorFromString:newText originalColor:weakSelf.currentTitleColor] forState:weakSelf.state]; + }]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Shadow Color" detailTitle:[self LL_hierarchyColorDescription:self.currentTitleShadowColor]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Shadow Color" detailTitle:[self LL_hierarchyColorDescription:self.currentTitleShadowColor]]; + model6.block = ^{ + [weakSelf LL_showTextFieldAlertWithText:[weakSelf.currentTitleShadowColor LL_HexString] handler:^(NSString * _Nullable newText) { + [weakSelf setTitleShadowColor:[weakSelf LL_colorFromString:newText originalColor:weakSelf.currentTitleShadowColor] forState:weakSelf.state]; + }]; + }; [settings addObject:model6]; id target = self.allTargets.allObjects.firstObject; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Target" detailTitle:target ? [NSString stringWithFormat:@"%@",target] : @""]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Target" detailTitle:target ? [NSString stringWithFormat:@"%@",target] : @""] noneInsets]; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_normalInsetsCellModelWithTitle:@"Action" detailTitle:[self LL_hierarchyTextDescription:[self actionsForTarget:target forControlEvent:UIControlEventTouchUpInside].firstObject]];; + LLTitleCellModel *model8 = [[LLTitleCellModel alloc] initWithTitle:@"Action" detailTitle:[self LL_hierarchyTextDescription:[self actionsForTarget:target forControlEvent:UIControlEventTouchUpInside].firstObject]];; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Image" detailTitle:[self LL_hierarchyImageDescription:self.currentImage]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Image" detailTitle:[self LL_hierarchyImageDescription:self.currentImage]]; [settings addObject:model9]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:self.titleShadowOffset]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:self.titleShadowOffset]] noneInsets]; + model10.block = ^{ + [weakSelf LL_showSizeAlertAndAutomicSetWithKeyPath:@"titleShadowOffset"]; + }; [settings addObject:model10]; #pragma clang diagnostic pop - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:@"On Highlight" detailTitle:self.reversesTitleShadowWhenHighlighted ? @"Shadow Reverses" : @"Normal Shadow"]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:@"On Highlight" detailTitle:self.reversesTitleShadowWhenHighlighted ? @"Shadow Reverses" : @"Normal Shadow"] noneInsets]; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:self.showsTouchWhenHighlighted ? @"Shows Touch" : @"Doesn't Show Touch"]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.showsTouchWhenHighlighted ? @"Shows Touch" : @"Doesn't Show Touch"] noneInsets]; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:self.adjustsImageWhenHighlighted ? @"Adjusts Image" : @"No Image Adjustment"]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:self.adjustsImageWhenHighlighted ? @"Adjusts Image" : @"No Image Adjustment"] noneInsets]; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_noneInsetsCellModelWithTitle:@"When Disabled" detailTitle:self.adjustsImageWhenDisabled ? @"Adjusts Image" : @"No Image Adjustment"]; + LLTitleCellModel *model14 = [[[LLTitleCellModel alloc] initWithTitle:@"When Disabled" detailTitle:self.adjustsImageWhenDisabled ? @"Adjusts Image" : @"No Image Adjustment"] noneInsets]; [settings addObject:model14]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - LLTitleCellModel *model15 = [self LL_normalInsetsCellModelWithTitle:@"Line Break" detailTitle:[LLEnumDescription lineBreakModeDescription:self.lineBreakMode]]; + LLTitleCellModel *model15 = [[LLTitleCellModel alloc] initWithTitle:@"Line Break" detailTitle:[LLEnumDescription lineBreakModeDescription:self.lineBreakMode]]; [settings addObject:model15]; #pragma clang diagnostic pop - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:@"Content Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.contentEdgeInsets]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:@"Content Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.contentEdgeInsets]] noneInsets]; + model16.block = ^{ + [weakSelf LL_showEdgeInsetsAndAutomicSetWithKeyPath:@"contentEdgeInsets"]; + }; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.contentEdgeInsets]]; + LLTitleCellModel *model17 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.contentEdgeInsets]] noneInsets]; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:@"Title Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.titleEdgeInsets]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.titleEdgeInsets]] noneInsets]; + model18.block = ^{ + [weakSelf LL_showEdgeInsetsAndAutomicSetWithKeyPath:@"titleEdgeInsets"]; + }; [settings addObject:model18]; - LLTitleCellModel *model19 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.titleEdgeInsets]]; + LLTitleCellModel *model19 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.titleEdgeInsets]] noneInsets]; [settings addObject:model19]; - LLTitleCellModel *model20 = [self LL_noneInsetsCellModelWithTitle:@"Image Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.imageEdgeInsets]]; + LLTitleCellModel *model20 = [[[LLTitleCellModel alloc] initWithTitle:@"Image Insets" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.imageEdgeInsets]] noneInsets]; + model20.block = ^{ + [weakSelf LL_showEdgeInsetsAndAutomicSetWithKeyPath:@"imageEdgeInsets"]; + }; [settings addObject:model20]; - LLTitleCellModel *model21 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.imageEdgeInsets]]; + LLTitleCellModel *model21 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.imageEdgeInsets]]; [settings addObject:model21]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Button" items:settings]; @@ -383,15 +842,21 @@ @implementation UIButton (LL_Hierarchy) @implementation UIImageView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Image" detailTitle: [self LL_hierarchyImageDescription:self.image]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Image" detailTitle: [self LL_hierarchyImageDescription:self.image]]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Highlighted" detailTitle: [self LL_hierarchyImageDescription:self.highlightedImage]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Highlighted" detailTitle: [self LL_hierarchyImageDescription:self.highlightedImage]]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"State" detailTitle:self.isHighlighted ? @"Highlighted" : @"Not Highlighted"]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"State" detailTitle:self.isHighlighted ? @"Highlighted" : @"Not Highlighted" flag:self.isHighlighted]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.highlighted = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Image View" items:settings]; @@ -410,69 +875,153 @@ @implementation UIImageView (LL_Hierarchy) @implementation UITextField (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Plain Text" detailTitle:[self LL_hierarchyTextDescription:self.text]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Plain Text" detailTitle:[self LL_hierarchyTextDescription:self.text]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"text"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Attributed Text" detailTitle:[self LL_hierarchyObjectDescription:self.attributedText]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Attributed Text" detailTitle:[self LL_hierarchyObjectDescription:self.attributedText]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showAttributeTextAlertAndAutomicSetWithKeyPath:@"attributedText"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Allows Editing Attributes %@", [self LL_hierarchyBoolDescription:self.allowsEditingTextAttributes]]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Allows Editing Attributes" flag:self.allowsEditingTextAttributes] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsEditingTextAttributes = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.textColor]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.textColor]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"textColor"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Font" detailTitle:[self LL_hierarchyObjectDescription:self.font]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Font" detailTitle:[self LL_hierarchyObjectDescription:self.font]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showFontAlertAndAutomicSetWithKeyPath:@"font"]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:@"Alignment" detailTitle:[LLEnumDescription textAlignmentDescription:self.textAlignment]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Alignment" detailTitle:[LLEnumDescription textAlignmentDescription:self.textAlignment]] noneInsets]; + model6.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAlignments] currentAction:[LLEnumDescription textAlignmentDescription:weakSelf.textAlignment] completion:^(NSInteger index) { + weakSelf.textAlignment = index; + }]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_normalInsetsCellModelWithTitle:@"Placeholder" detailTitle:[self LL_hierarchyTextDescription:self.placeholder ?: self.attributedPlaceholder.string]]; + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:@"Placeholder" detailTitle:[self LL_hierarchyTextDescription:self.placeholder ?: self.attributedPlaceholder.string]]; + model7.block = ^{ + if (weakSelf.placeholder) { + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"placeholder"]; + } else { + [weakSelf LL_showAttributeTextAlertAndAutomicSetWithKeyPath:@"attributedPlaceholder"]; + } + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Background" detailTitle: [self LL_hierarchyImageDescription:self.background]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Background" detailTitle: [self LL_hierarchyImageDescription:self.background]] noneInsets]; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Disabled" detailTitle: [self LL_hierarchyImageDescription:self.disabledBackground]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Disabled" detailTitle: [self LL_hierarchyImageDescription:self.disabledBackground]]; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_normalInsetsCellModelWithTitle:@"Border Style" detailTitle:[LLEnumDescription textBorderStyleDescription:self.borderStyle]]; + LLTitleCellModel *model10 = [[LLTitleCellModel alloc] initWithTitle:@"Border Style" detailTitle:[LLEnumDescription textBorderStyleDescription:self.borderStyle]]; + model10.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textBorderStyles] currentAction:[LLEnumDescription textBorderStyleDescription:weakSelf.borderStyle] completion:^(NSInteger index) { + weakSelf.borderStyle = index; + }]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:@"Clear Button" detailTitle:[LLEnumDescription textFieldViewModeDescription:self.clearButtonMode]]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:@"Clear Button" detailTitle:[LLEnumDescription textFieldViewModeDescription:self.clearButtonMode]] noneInsets]; + model11.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textFieldViewModes] currentAction:[LLEnumDescription textFieldViewModeDescription:weakSelf.clearButtonMode] completion:^(NSInteger index) { + weakSelf.clearButtonMode = index; + }]; + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Clear when editing begins %@", [self LL_hierarchyBoolDescription:self.clearsOnBeginEditing]]]; + LLTitleCellModel *model12 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Clear when editing begins" flag:self.clearsOnBeginEditing]; + model12.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.clearsOnBeginEditing = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:@"Min Font Size" detailTitle:[LLFormatterTool formatNumber:@(self.minimumFontSize)]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:@"Min Font Size" detailTitle:[LLFormatterTool formatNumber:@(self.minimumFontSize)]] noneInsets]; + model13.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"minimumFontSize"]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Adjusts to Fit %@",[self LL_hierarchyBoolDescription:self.adjustsFontSizeToFitWidth]]]; + LLTitleCellModel *model14 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Adjusts to Fit" flag:self.adjustsFontSizeToFitWidth]; + model14.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.adjustsFontSizeToFitWidth = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_noneInsetsCellModelWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]]; + LLTitleCellModel *model15 = [[[LLTitleCellModel alloc] initWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]] noneInsets]; + model15.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocapitalizationTypes] currentAction:[LLEnumDescription textAutocapitalizationTypeDescription:weakSelf.autocapitalizationType] completion:^(NSInteger index) { + weakSelf.autocapitalizationType = index; + }]; + }; [settings addObject:model15]; - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]] noneInsets]; + model16.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocorrectionTypes] currentAction:[LLEnumDescription textAutocorrectionTypeDescription:weakSelf.autocorrectionType] completion:^(NSInteger index) { + weakSelf.autocorrectionType = index; + }]; + }; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_noneInsetsCellModelWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]]; + LLTitleCellModel *model17 = [[[LLTitleCellModel alloc] initWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]] noneInsets]; + model17.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription keyboardTypes] currentAction:[LLEnumDescription keyboardTypeDescription:weakSelf.keyboardType] completion:^(NSInteger index) { + weakSelf.keyboardType = index; + }]; + }; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:@"Appearance" detailTitle:[LLEnumDescription keyboardAppearanceDescription:self.keyboardAppearance]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:@"Appearance" detailTitle:[LLEnumDescription keyboardAppearanceDescription:self.keyboardAppearance]] noneInsets]; + model18.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription keyboardAppearances] currentAction:[LLEnumDescription keyboardAppearanceDescription:weakSelf.keyboardAppearance] completion:^(NSInteger index) { + weakSelf.keyboardAppearance = index; + }]; + }; [settings addObject:model18]; - LLTitleCellModel *model19 = [self LL_noneInsetsCellModelWithTitle:@"Return Key" detailTitle:[LLEnumDescription returnKeyTypeDescription:self.returnKeyType]]; + LLTitleCellModel *model19 = [[[LLTitleCellModel alloc] initWithTitle:@"Return Key" detailTitle:[LLEnumDescription returnKeyTypeDescription:self.returnKeyType]] noneInsets]; + model19.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription returnKeyTypes] currentAction:[LLEnumDescription returnKeyTypeDescription:weakSelf.returnKeyType] completion:^(NSInteger index) { + weakSelf.returnKeyType = index; + }]; + }; [settings addObject:model19]; - LLTitleCellModel *model20 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Auto-enable Return Key %@", [self LL_hierarchyBoolDescription:self.enablesReturnKeyAutomatically]]]; + LLTitleCellModel *model20 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Auto-enable Return Key" flag:self.enablesReturnKeyAutomatically] noneInsets]; + model20.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.enablesReturnKeyAutomatically = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model20]; - LLTitleCellModel *model21 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Secure Entry %@",[self LL_hierarchyBoolDescription:self.secureTextEntry]]]; + LLTitleCellModel *model21 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Secure Entry" flag:self.isSecureTextEntry]; + model21.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.secureTextEntry = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model21]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Text Field" items:settings]; @@ -491,37 +1040,59 @@ @implementation UITextField (LL_Hierarchy) @implementation UISegmentedControl (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:self.isMomentary ? @"Momentary" : @"Persistent Selection"]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:self.isMomentary ? @"Momentary" : @"Persistent Selection" flag:self.isMomentary] noneInsets]; + model1.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.momentary = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Segments" detailTitle:[NSString stringWithFormat:@"%ld",(unsigned long)self.numberOfSegments]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Segments" detailTitle:[NSString stringWithFormat:@"%ld",(unsigned long)self.numberOfSegments]]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Selected Index" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.selectedSegmentIndex]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Selected Index" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.selectedSegmentIndex]] noneInsets]; + model3.block = ^{ + NSMutableArray *actions = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < weakSelf.numberOfSegments; i++) { + [actions addObject:[NSString stringWithFormat:@"%ld",(long)i]]; + } + [weakSelf LL_showActionSheetWithActions:actions currentAction:[NSString stringWithFormat:@"%ld",(long)weakSelf.selectedSegmentIndex] completion:^(NSInteger index) { + weakSelf.selectedSegmentIndex = index; + }]; + }; [settings addObject:model3]; #ifdef __IPHONE_13_0 if (@available(iOS 13.0, *)) { - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Title" detailTitle:[self LL_hierarchyTextDescription:self.largeContentTitle]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Large title" detailTitle:[self LL_hierarchyTextDescription:self.largeContentTitle]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"largeContentTitle"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Image" detailTitle: [self LL_hierarchyImageDescription:self.largeContentImage]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Image" detailTitle: [self LL_hierarchyImageDescription:self.largeContentImage]] noneInsets]; [settings addObject:model5]; } #endif - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Selected" detailTitle:[self isEnabledForSegmentAtIndex:self.selectedSegmentIndex] ? @"Enabled" : @"Not Enabled"]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Selected" detailTitle:[self isEnabledForSegmentAtIndex:self.selectedSegmentIndex] ? @"Enabled" : @"Not Enabled"]; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Offset" detailTitle:[self LL_hierarchySizeDescription:[self contentOffsetForSegmentAtIndex:self.selectedSegmentIndex]]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Offset" detailTitle:[self LL_hierarchySizeDescription:[self contentOffsetForSegmentAtIndex:self.selectedSegmentIndex]]] noneInsets]; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Size Mode" detailTitle:self.apportionsSegmentWidthsByContent ? @"Proportional to Content" : @"Equal Widths"]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Size Mode" detailTitle:self.apportionsSegmentWidthsByContent ? @"Proportional to Content" : @"Equal Widths" flag:self.apportionsSegmentWidthsByContent] noneInsets]; + model8.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.apportionsSegmentWidthsByContent = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Width" detailTitle:[LLFormatterTool formatNumber:@([self widthForSegmentAtIndex:self.selectedSegmentIndex])]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Width" detailTitle:[LLFormatterTool formatNumber:@([self widthForSegmentAtIndex:self.selectedSegmentIndex])]]; [settings addObject:model9]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Segmented Control" items:settings]; @@ -540,33 +1111,56 @@ @implementation UISegmentedControl (LL_Hierarchy) @implementation UISlider (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Current" detailTitle:[LLFormatterTool formatNumber:@(self.value)]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Current" detailTitle:[LLFormatterTool formatNumber:@(self.value)]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"value"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Minimum" detailTitle:[LLFormatterTool formatNumber:@(self.minimumValue)]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Minimum" detailTitle:[LLFormatterTool formatNumber:@(self.minimumValue)]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"minimumValue"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Maximum" detailTitle:[LLFormatterTool formatNumber:@(self.maximumValue)]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Maximum" detailTitle:[LLFormatterTool formatNumber:@(self.maximumValue)]]; + model3.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"maximumValue"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Min Image" detailTitle: [self LL_hierarchyImageDescription:self.minimumValueImage]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Min Image" detailTitle: [self LL_hierarchyImageDescription:self.minimumValueImage]] noneInsets]; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_normalInsetsCellModelWithTitle:@"Max Image" detailTitle: [self LL_hierarchyImageDescription:self.maximumValueImage]]; + LLTitleCellModel *model5 = [[LLTitleCellModel alloc] initWithTitle:@"Max Image" detailTitle: [self LL_hierarchyImageDescription:self.maximumValueImage]]; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:@"Min Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.minimumTrackTintColor]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Min Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.minimumTrackTintColor]] noneInsets]; + model6.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"minimumTrackTintColor"]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Max Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.maximumTrackTintColor]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Max Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.maximumTrackTintColor]] noneInsets]; + model7.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"maximumTrackTintColor"]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_normalInsetsCellModelWithTitle:@"Thumb Tint" detailTitle:[self LL_hierarchyColorDescription:self.tintColor]]; + LLTitleCellModel *model8 = [[LLTitleCellModel alloc] initWithTitle:@"Thumb Tint" detailTitle:[self LL_hierarchyColorDescription:self.tintColor]]; + model8.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"tintColor"]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Events" detailTitle:[NSString stringWithFormat:@"Continuous Update %@", [self LL_hierarchyBoolDescription:self.continuous]]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Events" detailTitle:@"Continuous Update" flag:self.isContinuous]; + model9.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.continuous = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model9]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Slider" items:settings]; @@ -585,15 +1179,26 @@ @implementation UISlider (LL_Hierarchy) @implementation UISwitch (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"State" detailTitle:[self LL_hierarchyBoolDescription:self.isOn]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"State" flag:self.isOn] noneInsets]; + model1.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.on = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"On Tint" detailTitle:[self LL_hierarchyColorDescription:self.onTintColor]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"On Tint" detailTitle:[self LL_hierarchyColorDescription:self.onTintColor]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"onTintColor"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Thumb Tint" detailTitle:[self LL_hierarchyColorDescription:self.thumbTintColor]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Thumb Tint" detailTitle:[self LL_hierarchyColorDescription:self.thumbTintColor]]; + model3.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"thumbTintColor"]; + }; [settings addObject:model3]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Switch" items:settings]; @@ -612,18 +1217,52 @@ @implementation UISwitch (LL_Hierarchy) @implementation UIActivityIndicatorView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription activityIndicatorViewStyleDescription:self.activityIndicatorViewStyle]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription activityIndicatorViewStyleDescription:self.activityIndicatorViewStyle]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription activityIndicatorViewStyles] currentAction:[LLEnumDescription activityIndicatorViewStyleDescription:weakSelf.activityIndicatorViewStyle] completion:^(NSInteger index) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (index <= UIActivityIndicatorViewStyleGray) { + weakSelf.activityIndicatorViewStyle = index; + } else { + if (@available(iOS 13.0, *)) { + weakSelf.activityIndicatorViewStyle = index + (UIActivityIndicatorViewStyleMedium - UIActivityIndicatorViewStyleGray - 1); + } + } +#pragma clang diagnostic pop + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.color]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.color]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"color"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:[NSString stringWithFormat:@"Animating %@", [self LL_hierarchyBoolDescription:self.isAnimating]]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:@"Animating" flag:self.isAnimating] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + if (!weakSelf.isAnimating) { + [weakSelf startAnimating]; + }; + } else { + if (weakSelf.isAnimating) { + [weakSelf stopAnimating]; + } + } + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Hides When Stopped %@", [self LL_hierarchyBoolDescription:self.hidesWhenStopped]]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Hides When Stopped" flag:self.hidesWhenStopped]; + model4.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.hidesWhenStopped = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model4]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Activity Indicator View" items:settings]; @@ -642,24 +1281,39 @@ @implementation UIActivityIndicatorView (LL_Hierarchy) @implementation UIProgressView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription progressViewStyleDescription:self.progressViewStyle]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription progressViewStyleDescription:self.progressViewStyle]]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription progressViewStyles] currentAction:[LLEnumDescription progressViewStyleDescription:weakSelf.progressViewStyle] completion:^(NSInteger index) { + weakSelf.progressViewStyle = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Progress" detailTitle:[LLFormatterTool formatNumber:@(self.progress)]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Progress" detailTitle:[LLFormatterTool formatNumber:@(self.progress)]]; + model2.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"progress"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Progress Tint" detailTitle:[self LL_hierarchyColorDescription:self.progressTintColor]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Progress Tint" detailTitle:[self LL_hierarchyColorDescription:self.progressTintColor]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"progressTintColor"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:@"Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.trackTintColor]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:@"Track Tint" detailTitle:[self LL_hierarchyColorDescription:self.trackTintColor]]; + model4.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"trackTintColor"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Progress Image" detailTitle:[self LL_hierarchyImageDescription:self.progressImage]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Progress Image" detailTitle:[self LL_hierarchyImageDescription:self.progressImage]] noneInsets]; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Track Image" detailTitle:[self LL_hierarchyImageDescription:self.trackImage]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Track Image" detailTitle:[self LL_hierarchyImageDescription:self.trackImage]]; [settings addObject:model6]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Progress View" items:settings]; @@ -678,24 +1332,55 @@ @implementation UIProgressView (LL_Hierarchy) @implementation UIPageControl (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Pages" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfPages]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Pages" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfPages]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"numberOfPages"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Current Page" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.currentPage]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Current Page" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.currentPage]] noneInsets]; + model2.block = ^{ + if (weakSelf.numberOfPages < 10) { + NSMutableArray *actions = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < weakSelf.numberOfPages; i++) { + [actions addObject:[NSString stringWithFormat:@"%ld",(long)i]]; + } + [weakSelf LL_showActionSheetWithActions:actions currentAction:[NSString stringWithFormat:@"%ld",(long)weakSelf.currentPage] completion:^(NSInteger index) { + weakSelf.currentPage = index; + }]; + } else { + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"currentPage"]; + } + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:[NSString stringWithFormat:@"Hides for Single Page %@",[self LL_hierarchyBoolDescription:self.hidesForSinglePage]]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:@"Hides for Single Page" flag:self.hidesForSinglePage] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.hidesForSinglePage = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Defers Page Display %@", [self LL_hierarchyBoolDescription:self.defersCurrentPageDisplay]]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Defers Page Display" flag:self.defersCurrentPageDisplay]; + model4.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.defersCurrentPageDisplay = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Tint Color" detailTitle:[self LL_hierarchyColorDescription:self.pageIndicatorTintColor]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Tint Color" detailTitle:[self LL_hierarchyColorDescription:self.pageIndicatorTintColor]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"pageIndicatorTintColor"]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Current Page" detailTitle:[self LL_hierarchyColorDescription:self.currentPageIndicatorTintColor]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Current Page" detailTitle:[self LL_hierarchyColorDescription:self.currentPageIndicatorTintColor]]; + model6.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"currentPageIndicatorTintColor"]; + }; [settings addObject:model6]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Page Control" items:settings]; @@ -714,27 +1399,54 @@ @implementation UIPageControl (LL_Hierarchy) @implementation UIStepper (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + + __weak typeof(self)weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Value" detailTitle:[LLFormatterTool formatNumber:@(self.value)]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Value" detailTitle:[LLFormatterTool formatNumber:@(self.value)]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"value"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Minimum" detailTitle:[LLFormatterTool formatNumber:@(self.minimumValue)]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Minimum" detailTitle:[LLFormatterTool formatNumber:@(self.minimumValue)]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"minimumValue"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Maximum" detailTitle:[LLFormatterTool formatNumber:@(self.maximumValue)]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Maximum" detailTitle:[LLFormatterTool formatNumber:@(self.maximumValue)]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"maximumValue"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:@"Step" detailTitle:[LLFormatterTool formatNumber:@(self.stepValue)]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:@"Step" detailTitle:[LLFormatterTool formatNumber:@(self.stepValue)]]; + model4.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"stepValue"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:[NSString stringWithFormat:@"Autorepeat %@",[self LL_hierarchyBoolDescription:self.autorepeat]]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:@"Autorepeat" flag:self.autorepeat] noneInsets]; + model5.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.autorepeat = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Continuous %@",[self LL_hierarchyBoolDescription:self.continuous]]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Continuous" flag:self.isContinuous] noneInsets]; + model6.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.continuous = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Wrap %@",[self LL_hierarchyBoolDescription:self.wraps]]]; + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Wrap" flag:self.wraps]; + model7.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.wraps = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model7]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Stepper" items:settings]; @@ -753,51 +1465,109 @@ @implementation UIStepper (LL_Hierarchy) @implementation UIScrollView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription scrollViewIndicatorStyleDescription:self.indicatorStyle]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription scrollViewIndicatorStyleDescription:self.indicatorStyle]]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription scrollViewIndicatorStyles] currentAction:[LLEnumDescription scrollViewIndicatorStyleDescription:weakSelf.indicatorStyle] completion:^(NSInteger index) { + weakSelf.indicatorStyle = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Indicators" detailTitle:[NSString stringWithFormat:@"Shows Horizontal Indicator %@",[self LL_hierarchyBoolDescription:self.showsHorizontalScrollIndicator]]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Indicators" detailTitle:@"Shows Horizontal Indicator" flag:self.showsHorizontalScrollIndicator] noneInsets]; + model2.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsHorizontalScrollIndicator = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shows Vertical Indicator %@",[self LL_hierarchyBoolDescription:self.showsVerticalScrollIndicator]]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shows Vertical Indicator" flag:self.showsVerticalScrollIndicator]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsVerticalScrollIndicator = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Scrolling" detailTitle:[NSString stringWithFormat:@"Scrolling %@", self.scrollEnabled ? @"Enabled" : @"Not Enabled"]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Scrolling" detailTitle:@"Enable" flag:self.isScrollEnabled] noneInsets]; + model4.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.scrollEnabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Paging %@", self.pagingEnabled ? @"Enabled" : @"Disabled"]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Paging" flag:self.isPagingEnabled] noneInsets]; + model5.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.pagingEnabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Direction Lock %@",self.isDirectionalLockEnabled ? @"Enabled" : @"Disabled"]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Direction Lock" flag:self.isDirectionalLockEnabled]; + model6.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.directionalLockEnabled = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Bounce" detailTitle:[NSString stringWithFormat:@"Bounces %@",[self LL_hierarchyBoolDescription:self.bounces]]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Bounce" detailTitle:@"Bounces" flag:self.bounces] noneInsets]; + model7.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.bounces = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Bounce Horizontal %@",[self LL_hierarchyBoolDescription:self.alwaysBounceHorizontal]]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Bounce Horizontal" flag:self.alwaysBounceHorizontal] noneInsets]; + model8.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.alwaysBounceHorizontal = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Bounce Vertical %@",[self LL_hierarchyBoolDescription:self.alwaysBounceVertical]]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Bounce Vertical" flag:self.alwaysBounceVertical]; + model9.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.alwaysBounceVertical = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Zoom Min" detailTitle:[LLFormatterTool formatNumber:@(self.minimumZoomScale)]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Zoom Min" detailTitle:[LLFormatterTool formatNumber:@(self.minimumZoomScale)]] noneInsets]; + model10.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"minimumZoomScale"]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_normalInsetsCellModelWithTitle:@"Max" detailTitle:[LLFormatterTool formatNumber:@(self.maximumZoomScale)]]; + LLTitleCellModel *model11 = [[LLTitleCellModel alloc] initWithTitle:@"Max" detailTitle:[LLFormatterTool formatNumber:@(self.maximumZoomScale)]]; + model11.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"maximumZoomScale"]; + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:@"Touch" detailTitle:[NSString stringWithFormat:@"Zoom Bounces %@",[self LL_hierarchyBoolDescription:self.isZoomBouncing]]]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:@"Touch" detailTitle:[NSString stringWithFormat:@"Zoom Bounces %@",[self LL_hierarchyBoolDescription:self.isZoomBouncing]]] noneInsets]; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Delays Content Touches %@",[self LL_hierarchyBoolDescription:self.delaysContentTouches]]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Delays Content Touches" flag:self.delaysContentTouches] noneInsets]; + model13.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.delaysContentTouches = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Cancellable Content Touches %@",[self LL_hierarchyBoolDescription:self.canCancelContentTouches]]]; + LLTitleCellModel *model14 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Cancellable Content Touches" flag:self.canCancelContentTouches]; + model14.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.canCancelContentTouches = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_normalInsetsCellModelWithTitle:@"Keyboard" detailTitle:[LLEnumDescription scrollViewKeyboardDismissModeDescription:self.keyboardDismissMode]]; + LLTitleCellModel *model15 = [[LLTitleCellModel alloc] initWithTitle:@"Keyboard" detailTitle:[LLEnumDescription scrollViewKeyboardDismissModeDescription:self.keyboardDismissMode]]; + model15.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription scrollViewKeyboardDismissModes] currentAction:[LLEnumDescription scrollViewKeyboardDismissModeDescription:weakSelf.keyboardDismissMode] completion:^(NSInteger index) { + weakSelf.keyboardDismissMode = index; + }]; + }; [settings addObject:model15]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Scroll View" items:settings]; @@ -816,68 +1586,125 @@ @implementation UIScrollView (LL_Hierarchy) @implementation UITableView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Sections" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfSections]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Sections" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfSections]] noneInsets]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription tableViewStyleDescription:self.style]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription tableViewStyleDescription:self.style]] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Separator" detailTitle:[LLEnumDescription tableViewCellSeparatorStyleDescription:self.separatorStyle]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Separator" detailTitle:[LLEnumDescription tableViewCellSeparatorStyleDescription:self.separatorStyle]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tableViewCellSeparatorStyles] currentAction:[LLEnumDescription tableViewCellSeparatorStyleDescription:weakSelf.separatorStyle] completion:^(NSInteger index) { + weakSelf.separatorStyle = index; + }]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyColorDescription:self.separatorColor]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyColorDescription:self.separatorColor]]; + model4.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"separatorColor"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Data Source" detailTitle:[self LL_hierarchyObjectDescription:self.dataSource]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Data Source" detailTitle:[self LL_hierarchyObjectDescription:self.dataSource]] noneInsets]; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]]; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Separator Inset" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.separatorInset]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Separator Inset" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.separatorInset]] noneInsets]; + model7.block = ^{ + [weakSelf LL_showEdgeInsetsAndAutomicSetWithKeyPath:@"separatorInset"]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.separatorInset]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.separatorInset]] noneInsets]; [settings addObject:model8]; if (@available(iOS 11.0, *)) { - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[LLEnumDescription tableViewSeparatorInsetReferenceDescription:self.separatorInsetReference]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[LLEnumDescription tableViewSeparatorInsetReferenceDescription:self.separatorInsetReference]]; + model9.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tableViewSeparatorInsetReferences] currentAction:[LLEnumDescription tableViewSeparatorInsetReferenceDescription:weakSelf.separatorInsetReference] completion:^(NSInteger index) { + weakSelf.separatorInsetReference = index; + }]; + }; [settings addObject:model9]; } - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Selection" detailTitle:self.allowsSelection ? @"Allowed" : @"Disabled"]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Selection" detailTitle:self.allowsSelection ? @"Allowed" : @"Disabled" flag:self.allowsSelection] noneInsets]; + model10.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsSelection = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Multiple Selection %@",self.allowsMultipleSelection ? @"" : @"Disabled"]]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[NSString stringWithFormat:@"Multiple Selection %@",self.allowsMultipleSelection ? @"" : @"Disabled"] flag:self.allowsMultipleSelection] noneInsets]; + model11.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsMultipleSelection = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:@"Edit Selection" detailTitle:self.allowsSelectionDuringEditing ? @"Allowed" : @"Disabled"]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:@"Edit Selection" detailTitle:self.allowsSelectionDuringEditing ? @"Allowed" : @"Disabled" flag:self.allowsSelectionDuringEditing] noneInsets]; + model12.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsSelectionDuringEditing = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Multiple Selection %@",self.allowsMultipleSelection ? @"" : @"Disabled"]]; + LLTitleCellModel *model13 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[NSString stringWithFormat:@"Multiple Selection %@",self.allowsMultipleSelectionDuringEditing ? @"" : @"Disabled"] flag:self.allowsMultipleSelectionDuringEditing]; + model13.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsMultipleSelectionDuringEditing = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_noneInsetsCellModelWithTitle:@"Min Display" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.sectionIndexMinimumDisplayRowCount]]; + LLTitleCellModel *model14 = [[[LLTitleCellModel alloc] initWithTitle:@"Min Display" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.sectionIndexMinimumDisplayRowCount]] noneInsets]; + model14.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"sectionIndexMinimumDisplayRowCount"]; + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_noneInsetsCellModelWithTitle:@"Text" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexColor]]; + LLTitleCellModel *model15 = [[[LLTitleCellModel alloc] initWithTitle:@"Text" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexColor]] noneInsets]; + model15.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"sectionIndexColor"]; + }; [settings addObject:model15]; - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:@"Background" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexBackgroundColor]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:@"Background" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexBackgroundColor]] noneInsets]; + model16.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"sectionIndexBackgroundColor"]; + }; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_normalInsetsCellModelWithTitle:@"Tracking" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexTrackingBackgroundColor]]; + LLTitleCellModel *model17 = [[LLTitleCellModel alloc] initWithTitle:@"Tracking" detailTitle:[self LL_hierarchyColorDescription:self.sectionIndexTrackingBackgroundColor]]; + model17.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"sectionIndexTrackingBackgroundColor"]; + }; + model17.block = ^{ + + }; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:@"Row Height" detailTitle:[LLFormatterTool formatNumber:@(self.rowHeight)]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:@"Row Height" detailTitle:[LLFormatterTool formatNumber:@(self.rowHeight)]] noneInsets]; + model18.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"rowHeight"]; + }; [settings addObject:model18]; - LLTitleCellModel *model19 = [self LL_noneInsetsCellModelWithTitle:@"Section Header" detailTitle:[LLFormatterTool formatNumber:@(self.sectionHeaderHeight)]]; + LLTitleCellModel *model19 = [[[LLTitleCellModel alloc] initWithTitle:@"Section Header" detailTitle:[LLFormatterTool formatNumber:@(self.sectionHeaderHeight)]] noneInsets]; + model19.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"sectionHeaderHeight"]; + }; [settings addObject:model19]; - LLTitleCellModel *model20 = [self LL_normalInsetsCellModelWithTitle:@"Section Footer" detailTitle:[LLFormatterTool formatNumber:@(self.sectionFooterHeight)]]; + LLTitleCellModel *model20 = [[LLTitleCellModel alloc] initWithTitle:@"Section Footer" detailTitle:[LLFormatterTool formatNumber:@(self.sectionFooterHeight)]]; + model20.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"sectionFooterHeight"]; + }; [settings addObject:model20]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Table View" items:settings]; @@ -896,40 +1723,72 @@ @implementation UITableView (LL_Hierarchy) @implementation UITableViewCell (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { - + __weak typeof(self) weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Image" detailTitle:[self LL_hierarchyImageDescription:self.imageView.image]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Image" detailTitle:[self LL_hierarchyImageDescription:self.imageView.image]]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Identifier" detailTitle:[self LL_hierarchyTextDescription:self.reuseIdentifier]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Identifier" detailTitle:[self LL_hierarchyTextDescription:self.reuseIdentifier]]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Selection" detailTitle:[LLEnumDescription tableViewCellSelectionStyleDescription:self.selectionStyle]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Selection" detailTitle:[LLEnumDescription tableViewCellSelectionStyleDescription:self.selectionStyle]] noneInsets]; + model3.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tableViewCellSelectionStyles] currentAction:[LLEnumDescription tableViewCellSelectionStyleDescription:weakSelf.selectionStyle] completion:^(NSInteger index) { + weakSelf.selectionStyle = index; + }]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Accessory" detailTitle:[LLEnumDescription tableViewCellAccessoryTypeDescription:self.accessoryType]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Accessory" detailTitle:[LLEnumDescription tableViewCellAccessoryTypeDescription:self.accessoryType]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tableViewCellAccessoryTypes] currentAction:[LLEnumDescription tableViewCellAccessoryTypeDescription:weakSelf.accessoryType] completion:^(NSInteger index) { + weakSelf.accessoryType = index; + }]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_normalInsetsCellModelWithTitle:@"Editing Acc." detailTitle:[LLEnumDescription tableViewCellAccessoryTypeDescription:self.editingAccessoryType]]; + LLTitleCellModel *model5 = [[LLTitleCellModel alloc] initWithTitle:@"Editing Acc." detailTitle:[LLEnumDescription tableViewCellAccessoryTypeDescription:self.editingAccessoryType]]; + model5.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tableViewCellAccessoryTypes] currentAction:[LLEnumDescription tableViewCellAccessoryTypeDescription:weakSelf.editingAccessoryType] completion:^(NSInteger index) { + weakSelf.editingAccessoryType = index; + }]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:@"Indentation" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.indentationLevel]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Indentation" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.indentationLevel]] noneInsets]; + model6.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"indentationLevel"]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[LLFormatterTool formatNumber:@(self.indentationWidth)]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[LLFormatterTool formatNumber:@(self.indentationWidth)]] noneInsets]; + model7.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"indentationWidth"]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Indent While Editing %@",[self LL_hierarchyBoolDescription:self.shouldIndentWhileEditing]]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Indent While Editing" flag:self.shouldIndentWhileEditing] noneInsets]; + model8.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.shouldIndentWhileEditing = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shows Re-order Controls %@",[self LL_hierarchyBoolDescription:self.showsReorderControl]]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shows Re-order Controls" flag:self.showsReorderControl]; + model9.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsReorderControl = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Separator Inset" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.separatorInset]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Separator Inset" detailTitle:[self LL_hierarchyInsetsTopBottomDescription:self.separatorInset]] noneInsets]; + model10.block = ^{ + [weakSelf LL_showEdgeInsetsAndAutomicSetWithKeyPath:@"separatorInset"]; + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.separatorInset]]; + LLTitleCellModel *model11 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyInsetsLeftRightDescription:self.separatorInset]]; [settings addObject:model11]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Table View Cell" items:settings]; @@ -950,16 +1809,16 @@ @implementation UICollectionView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Sections" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfSections]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Sections" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.numberOfSections]]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:@"Data Source" detailTitle:[self LL_hierarchyObjectDescription:self.dataSource]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:@"Data Source" detailTitle:[self LL_hierarchyObjectDescription:self.dataSource]] noneInsets]; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_normalInsetsCellModelWithTitle:@"Layout" detailTitle:[self LL_hierarchyObjectDescription:self.collectionViewLayout]]; + LLTitleCellModel *model4 = [[LLTitleCellModel alloc] initWithTitle:@"Layout" detailTitle:[self LL_hierarchyObjectDescription:self.collectionViewLayout]]; [settings addObject:model4]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Collection View" items:settings]; @@ -980,7 +1839,7 @@ @implementation UICollectionReusableView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Identifier" detailTitle:[self LL_hierarchyTextDescription:self.reuseIdentifier]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Identifier" detailTitle:[self LL_hierarchyTextDescription:self.reuseIdentifier]] noneInsets]; [settings addObject:model1]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Collection Reusable View" items:settings]; @@ -999,76 +1858,189 @@ @implementation UICollectionReusableView (LL_Hierarchy) @implementation UITextView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Plain Text" detailTitle:[self LL_hierarchyTextDescription:self.text]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Plain Text" detailTitle:[self LL_hierarchyTextDescription:self.text]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"text"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Attributed Text" detailTitle:[self LL_hierarchyObjectDescription:self.attributedText]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Attributed Text" detailTitle:[self LL_hierarchyObjectDescription:self.attributedText]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showAttributeTextAlertAndAutomicSetWithKeyPath:@"attributedText"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Allows Editing Attributes %@",[self LL_hierarchyBoolDescription:self.allowsEditingTextAttributes]]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Allows Editing Attributes" flag:self.allowsEditingTextAttributes] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.allowsEditingTextAttributes = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.textColor]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Color" detailTitle:[self LL_hierarchyColorDescription:self.textColor]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"textColor"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Font" detailTitle:[self LL_hierarchyObjectDescription:self.font]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Font" detailTitle:[self LL_hierarchyObjectDescription:self.font]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showFontAlertAndAutomicSetWithKeyPath:@"font"]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Alignment" detailTitle:[LLEnumDescription textAlignmentDescription:self.textAlignment]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Alignment" detailTitle:[LLEnumDescription textAlignmentDescription:self.textAlignment]]; + model6.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAlignments] currentAction:[LLEnumDescription textAlignmentDescription:weakSelf.textAlignment] completion:^(NSInteger index) { + weakSelf.textAlignment = index; + }]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Behavior" detailTitle:[NSString stringWithFormat:@"Editable %@",[self LL_hierarchyBoolDescription:self.isEditable]]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Behavior" detailTitle:@"Editable" flag:self.isEditable] noneInsets]; + model7.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.editable = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Selectable %@",[self LL_hierarchyBoolDescription:self.isSelectable]]]; + LLTitleCellModel *model8 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Selectable" flag:self.isSelectable]; + model8.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.selectable = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_noneInsetsCellModelWithTitle:@"Data Detectors" detailTitle:[NSString stringWithFormat:@"Phone Number %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypePhoneNumber]]]; + LLTitleCellModel *model9 = [[[LLTitleCellModel alloc] initWithTitle:@"Data Detectors" detailTitle:@"Phone Number" flag:self.dataDetectorTypes & UIDataDetectorTypePhoneNumber] noneInsets]; + model9.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypePhoneNumber; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypePhoneNumber; + } + }; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Link %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeLink]]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Link" flag:self.dataDetectorTypes & UIDataDetectorTypeLink] noneInsets]; + model10.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeLink; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeLink; + } + }; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Address %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeAddress]]]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Address" flag:self.dataDetectorTypes & UIDataDetectorTypeAddress] noneInsets]; + model11.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeAddress; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeAddress; + } + }; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Calendar Event %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeCalendarEvent]]]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Calendar Event" flag:self.dataDetectorTypes & UIDataDetectorTypeCalendarEvent] noneInsets]; + model12.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeCalendarEvent; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeCalendarEvent; + } + }; [settings addObject:model12]; if (@available(iOS 10.0, *)) { - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shipment Tracking Number %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeShipmentTrackingNumber]]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shipment Tracking Number" flag:self.dataDetectorTypes & UIDataDetectorTypeShipmentTrackingNumber] noneInsets]; + model13.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeShipmentTrackingNumber; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeShipmentTrackingNumber; + } + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Flight Number %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeFlightNumber]]]; + LLTitleCellModel *model14 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Flight Number" flag:self.dataDetectorTypes & UIDataDetectorTypeFlightNumber] noneInsets]; + model14.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeFlightNumber; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeFlightNumber; + } + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Lookup Suggestion %@",[self LL_hierarchyBoolDescription:self.dataDetectorTypes & UIDataDetectorTypeLookupSuggestion]]]; + LLTitleCellModel *model15 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Lookup Suggestion" flag:self.dataDetectorTypes & UIDataDetectorTypeLookupSuggestion]; + model15.changePropertyBlock = ^(id _Nullable obj) { + if ([obj boolValue]) { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes | UIDataDetectorTypeLookupSuggestion; + } else { + weakSelf.dataDetectorTypes = weakSelf.dataDetectorTypes & ~UIDataDetectorTypeLookupSuggestion; + } + }; [settings addObject:model15]; } else { - model12.separatorInsets = UIEdgeInsetsMake(0, kLLGeneralMargin, 0, 0); + [model12 normalInsets]; } - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]] noneInsets]; + model16.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocapitalizationTypes] currentAction:[LLEnumDescription textAutocapitalizationTypeDescription:weakSelf.autocapitalizationType] completion:^(NSInteger index) { + weakSelf.autocapitalizationType = index; + }]; + }; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_noneInsetsCellModelWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]]; + LLTitleCellModel *model17 = [[[LLTitleCellModel alloc] initWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]] noneInsets]; + model17.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocorrectionTypes] currentAction:[LLEnumDescription textAutocorrectionTypeDescription:weakSelf.autocorrectionType] completion:^(NSInteger index) { + weakSelf.autocorrectionType = index; + }]; + }; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]] noneInsets]; + model18.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription keyboardTypes] currentAction:[LLEnumDescription keyboardTypeDescription:weakSelf.keyboardType] completion:^(NSInteger index) { + weakSelf.keyboardType = index; + }]; + }; [settings addObject:model18]; - LLTitleCellModel *model19 = [self LL_noneInsetsCellModelWithTitle:@"Appearance" detailTitle:[LLEnumDescription keyboardAppearanceDescription:self.keyboardAppearance]]; + LLTitleCellModel *model19 = [[[LLTitleCellModel alloc] initWithTitle:@"Appearance" detailTitle:[LLEnumDescription keyboardAppearanceDescription:self.keyboardAppearance]] noneInsets]; + model19.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription keyboardAppearances] currentAction:[LLEnumDescription keyboardAppearanceDescription:weakSelf.keyboardAppearance] completion:^(NSInteger index) { + weakSelf.keyboardAppearance = index; + }]; + }; [settings addObject:model19]; - LLTitleCellModel *model20 = [self LL_noneInsetsCellModelWithTitle:@"Return Key" detailTitle:[LLEnumDescription returnKeyTypeDescription:self.returnKeyType]]; + LLTitleCellModel *model20 = [[[LLTitleCellModel alloc] initWithTitle:@"Return Key" detailTitle:[LLEnumDescription returnKeyTypeDescription:self.returnKeyType]] noneInsets]; + model20.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription returnKeyTypes] currentAction:[LLEnumDescription returnKeyTypeDescription:weakSelf.returnKeyType] completion:^(NSInteger index) { + weakSelf.returnKeyType = index; + }]; + }; [settings addObject:model20]; - LLTitleCellModel *model21 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Auto-enable Return Key %@",[self LL_hierarchyBoolDescription:self.enablesReturnKeyAutomatically]]]; + LLTitleCellModel *model21 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Auto-enable Return Key" flag:self.enablesReturnKeyAutomatically] noneInsets]; + model21.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.enablesReturnKeyAutomatically = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model21]; - LLTitleCellModel *model22 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Secure Entry %@",[self LL_hierarchyBoolDescription:self.isSecureTextEntry]]]; + LLTitleCellModel *model22 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Secure Entry" flag:self.isSecureTextEntry]; + model22.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.secureTextEntry = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model22]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Text View" items:settings]; @@ -1087,32 +2059,47 @@ @implementation UITextView (LL_Hierarchy) @implementation UIDatePicker (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Mode" detailTitle:[LLEnumDescription datePickerModeDescription:self.datePickerMode]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Mode" detailTitle:[LLEnumDescription datePickerModeDescription:self.datePickerMode]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription datePickerModes] currentAction:[LLEnumDescription datePickerModeDescription:weakSelf.datePickerMode] completion:^(NSInteger index) { + weakSelf.datePickerMode = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Locale Identifier" detailTitle:self.locale.localeIdentifier]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Locale Identifier" detailTitle:self.locale.localeIdentifier] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Interval" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.minuteInterval]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Interval" detailTitle:[NSString stringWithFormat:@"%ld",(long)self.minuteInterval]]; + model3.block = ^{ + [weakSelf LL_showIntAlertAndAutomicSetWithKeyPath:@"minuteInterval"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Date" detailTitle:[self LL_hierarchyObjectDescription:self.date]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Date" detailTitle:[self LL_hierarchyDateDescription:self.date]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showDateAlertAndAutomicSetWithKeyPath:@"date"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Min Date" detailTitle:[self LL_hierarchyObjectDescription:self.minimumDate]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Min Date" detailTitle:[self LL_hierarchyDateDescription:self.minimumDate]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showDateAlertAndAutomicSetWithKeyPath:@"minimumDate"]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Max Date" detailTitle:[self LL_hierarchyObjectDescription:self.maximumDate]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Max Date" detailTitle:[self LL_hierarchyDateDescription:self.maximumDate]]; + model6.block = ^{ + [weakSelf LL_showDateAlertAndAutomicSetWithKeyPath:@"maximumDate"]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Count Down" detailTitle:[LLFormatterTool formatNumber:@(self.countDownDuration)]]; + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:@"Count Down" detailTitle:[LLFormatterTool formatNumber:@(self.countDownDuration)]]; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:@"Count Down in Seconds"]; - [settings addObject:model8]; - LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Date Picker" items:settings]; NSMutableArray *models = [[NSMutableArray alloc] initWithArray:[super LL_hierarchyCategoryModels]]; @@ -1131,7 +2118,7 @@ @implementation UIPickerView (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_normalInsetsCellModelWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]]; + LLTitleCellModel *model1 = [[LLTitleCellModel alloc] initWithTitle:@"Delegate" detailTitle:[self LL_hierarchyObjectDescription:self.delegate]]; [settings addObject:model1]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Picker View" items:settings]; @@ -1150,38 +2137,69 @@ @implementation UIPickerView (LL_Hierarchy) @implementation UINavigationBar (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self)weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription barStyles] currentAction:[LLEnumDescription barStyleDescription:weakSelf.barStyle] completion:^(NSInteger index) { + weakSelf.barStyle = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Translucent %@",[self LL_hierarchyBoolDescription:self.isTranslucent]]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Translucent" flag:self.isTranslucent] noneInsets]; + model2.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.translucent = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model2]; if (@available(iOS 11.0, *)) { - LLTitleCellModel *model3 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Prefers Large Titles %@",[self LL_hierarchyBoolDescription:self.prefersLargeTitles]]]; + LLTitleCellModel *model3 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Prefers Large Titles" flag:self.prefersLargeTitles] noneInsets]; + model3.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.prefersLargeTitles = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model3]; } - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"barTintColor"]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Shadow Image" detailTitle:[self LL_hierarchyImageDescription:self.shadowImage]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow Image" detailTitle:[self LL_hierarchyImageDescription:self.shadowImage]] noneInsets]; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:@"Back Image" detailTitle:[self LL_hierarchyImageDescription:self.backIndicatorImage]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:@"Back Image" detailTitle:[self LL_hierarchyImageDescription:self.backIndicatorImage]] noneInsets]; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_normalInsetsCellModelWithTitle:@"Back Mask" detailTitle:[self LL_hierarchyImageDescription:self.backIndicatorTransitionMaskImage]]; + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:@"Back Mask" detailTitle:[self LL_hierarchyImageDescription:self.backIndicatorTransitionMaskImage]]; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Title Attr." detailTitle:nil]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Attr." detailTitle:nil] noneInsets]; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_noneInsetsCellModelWithTitle:@"Title Font" detailTitle:[self LL_hierarchyColorDescription:self.titleTextAttributes[NSFontAttributeName]]]; + LLTitleCellModel *model9 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Font" detailTitle:[self LL_hierarchyObjectDescription:self.titleTextAttributes[NSFontAttributeName]]] noneInsets]; + if (self.titleTextAttributes[NSFontAttributeName]) { + model9.block = ^{ + __block UIFont *font = weakSelf.titleTextAttributes[NSFontAttributeName]; + if (!font) { + return; + } + [weakSelf LL_showTextFieldAlertWithText:[NSString stringWithFormat:@"%@",[LLFormatterTool formatNumber:@(font.pointSize)]] handler:^(NSString * _Nullable newText) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithDictionary:weakSelf.titleTextAttributes]; + attributes[NSFontAttributeName] = [font fontWithSize:[newText doubleValue]]; + weakSelf.titleTextAttributes = [attributes copy]; + }]; + }; + } [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Title Color" detailTitle:[self LL_hierarchyColorDescription:self.titleTextAttributes[NSForegroundColorAttributeName]]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Color" detailTitle:[self LL_hierarchyColorDescription:self.titleTextAttributes[NSForegroundColorAttributeName]]] noneInsets]; [settings addObject:model10]; NSShadow *shadow = self.titleTextAttributes[NSShadowAttributeName]; @@ -1189,20 +2207,33 @@ @implementation UINavigationBar (LL_Hierarchy) shadow = nil; } - LLTitleCellModel *model11 = [self LL_noneInsetsCellModelWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:shadow.shadowColor]]; + LLTitleCellModel *model11 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:shadow.shadowColor]] noneInsets]; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_normalInsetsCellModelWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:shadow.shadowOffset]]; + LLTitleCellModel *model12 = [[LLTitleCellModel alloc] initWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:shadow.shadowOffset]]; [settings addObject:model12]; if (@available(iOS 11.0, *)) { - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:@"Large Title Attr." detailTitle:nil]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:@"Large Title Attr." detailTitle:nil] noneInsets]; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_noneInsetsCellModelWithTitle:@"Title Font" detailTitle:[self LL_hierarchyColorDescription:self.largeTitleTextAttributes[NSFontAttributeName]]]; + LLTitleCellModel *model14 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Font" detailTitle:[self LL_hierarchyColorDescription:self.largeTitleTextAttributes[NSFontAttributeName]]] noneInsets]; + if (self.largeTitleTextAttributes[NSFontAttributeName]) { + model14.block = ^{ + __block UIFont *font = weakSelf.largeTitleTextAttributes[NSFontAttributeName]; + if (!font) { + return; + } + [weakSelf LL_showTextFieldAlertWithText:[NSString stringWithFormat:@"%@",[LLFormatterTool formatNumber:@(font.pointSize)]] handler:^(NSString * _Nullable newText) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithDictionary:weakSelf.largeTitleTextAttributes]; + attributes[NSFontAttributeName] = [font fontWithSize:[newText doubleValue]]; + weakSelf.largeTitleTextAttributes = [attributes copy]; + }]; + }; + } [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_noneInsetsCellModelWithTitle:@"Title Color" detailTitle:[self LL_hierarchyColorDescription:self.largeTitleTextAttributes[NSForegroundColorAttributeName]]]; + LLTitleCellModel *model15 = [[[LLTitleCellModel alloc] initWithTitle:@"Title Color" detailTitle:[self LL_hierarchyColorDescription:self.largeTitleTextAttributes[NSForegroundColorAttributeName]]] noneInsets]; [settings addObject:model15]; shadow = self.largeTitleTextAttributes[NSShadowAttributeName]; @@ -1210,10 +2241,10 @@ @implementation UINavigationBar (LL_Hierarchy) shadow = nil; } - LLTitleCellModel *model16 = [self LL_noneInsetsCellModelWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:shadow.shadowColor]]; + LLTitleCellModel *model16 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow" detailTitle:[self LL_hierarchyColorDescription:shadow.shadowColor]] noneInsets]; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_normalInsetsCellModelWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:shadow.shadowOffset]]; + LLTitleCellModel *model17 = [[LLTitleCellModel alloc] initWithTitle:@"Shadow Offset" detailTitle:[self LL_hierarchySizeDescription:shadow.shadowOffset]]; [settings addObject:model17]; } @@ -1233,15 +2264,29 @@ @implementation UINavigationBar (LL_Hierarchy) @implementation UIToolbar (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; + NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription barStyles] currentAction:[LLEnumDescription barStyleDescription:weakSelf.barStyle] completion:^(NSInteger index) { + weakSelf.barStyle = index; + }]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Translucent %@",[self LL_hierarchyBoolDescription:self.isTranslucent]]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Translucent" flag:self.isTranslucent] noneInsets]; + model2.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.translucent = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + model3.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"barTintColor"]; + }; [settings addObject:model3]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Tool Bar" items:settings]; @@ -1260,33 +2305,57 @@ @implementation UIToolbar (LL_Hierarchy) @implementation UITabBar (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Background" detailTitle:[self LL_hierarchyImageDescription:self.backgroundImage]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Background" detailTitle:[self LL_hierarchyImageDescription:self.backgroundImage]] noneInsets]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Shadow" detailTitle:[self LL_hierarchyImageDescription:self.shadowImage]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Shadow" detailTitle:[self LL_hierarchyImageDescription:self.shadowImage]] noneInsets]; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Selection" detailTitle:[self LL_hierarchyImageDescription:self.selectionIndicatorImage]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Selection" detailTitle:[self LL_hierarchyImageDescription:self.selectionIndicatorImage]]; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription barStyles] currentAction:[LLEnumDescription barStyleDescription:weakSelf.barStyle] completion:^(NSInteger index) { + weakSelf.barStyle = index; + }]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Translucent %@",[self LL_hierarchyBoolDescription:self.isTranslucent]]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Translucent" flag:self.isTranslucent] noneInsets]; + model5.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.translucent = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_normalInsetsCellModelWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + LLTitleCellModel *model6 = [[LLTitleCellModel alloc] initWithTitle:@"Bar Tint" detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + model6.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"barTintColor"]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_noneInsetsCellModelWithTitle:@"Style" detailTitle:[LLEnumDescription tabBarItemPositioningDescription:self.itemPositioning]]; + LLTitleCellModel *model7 = [[[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLEnumDescription tabBarItemPositioningDescription:self.itemPositioning]] noneInsets]; + model7.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription tabBarItemPositionings] currentAction:[LLEnumDescription tabBarItemPositioningDescription:weakSelf.itemPositioning] completion:^(NSInteger index) { + weakSelf.itemPositioning = index; + }]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Item Width" detailTitle:[LLFormatterTool formatNumber:@(self.itemWidth)]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Item Width" detailTitle:[LLFormatterTool formatNumber:@(self.itemWidth)]] noneInsets]; + model8.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"itemWidth"]; + }; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Item Spacing" detailTitle:[LLFormatterTool formatNumber:@(self.itemSpacing)]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Item Spacing" detailTitle:[LLFormatterTool formatNumber:@(self.itemSpacing)]]; + model9.block = ^{ + [weakSelf LL_showDoubleAlertAndAutomicSetWithKeyPath:@"itemSpacing"]; + }; [settings addObject:model9]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Tab Bar" items:settings]; @@ -1305,63 +2374,121 @@ @implementation UITabBar (LL_Hierarchy) @implementation UISearchBar (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { + __weak typeof(self) weakSelf = self; NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:@"Text" detailTitle:[self LL_hierarchyTextDescription:self.text]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:@"Text" detailTitle:[self LL_hierarchyTextDescription:self.text]] noneInsets]; + model1.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"text"]; + }; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_noneInsetsCellModelWithTitle:@"Placeholder" detailTitle:[self LL_hierarchyTextDescription:self.placeholder]]; + LLTitleCellModel *model2 = [[[LLTitleCellModel alloc] initWithTitle:@"Placeholder" detailTitle:[self LL_hierarchyTextDescription:self.placeholder]] noneInsets]; + model2.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"placeholder"]; + }; [settings addObject:model2]; - LLTitleCellModel *model3 = [self LL_normalInsetsCellModelWithTitle:@"Prompt" detailTitle:[self LL_hierarchyTextDescription:self.prompt]]; + LLTitleCellModel *model3 = [[LLTitleCellModel alloc] initWithTitle:@"Prompt" detailTitle:[self LL_hierarchyTextDescription:self.prompt]]; + model3.block = ^{ + [weakSelf LL_showTextAlertAndAutomicSetWithKeyPath:@"prompt"]; + }; [settings addObject:model3]; - LLTitleCellModel *model4 = [self LL_noneInsetsCellModelWithTitle:@"Search Style" detailTitle:[LLEnumDescription searchBarStyleDescription:self.searchBarStyle]]; + LLTitleCellModel *model4 = [[[LLTitleCellModel alloc] initWithTitle:@"Search Style" detailTitle:[LLEnumDescription searchBarStyleDescription:self.searchBarStyle]] noneInsets]; + model4.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription searchBarStyles] currentAction:[LLEnumDescription searchBarStyleDescription:weakSelf.searchBarStyle] completion:^(NSInteger index) { + weakSelf.searchBarStyle = index; + }]; + }; [settings addObject:model4]; - LLTitleCellModel *model5 = [self LL_noneInsetsCellModelWithTitle:@"Bar Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]]; + LLTitleCellModel *model5 = [[[LLTitleCellModel alloc] initWithTitle:@"Bar Style" detailTitle:[LLEnumDescription barStyleDescription:self.barStyle]] noneInsets]; + model5.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription barStyles] currentAction:[LLEnumDescription barStyleDescription:weakSelf.barStyle] completion:^(NSInteger index) { + weakSelf.barStyle = index; + }]; + }; [settings addObject:model5]; - LLTitleCellModel *model6 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Translucent %@",[self LL_hierarchyBoolDescription:self.isTranslucent]]]; + LLTitleCellModel *model6 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Translucent" flag:self.isTranslucent] noneInsets]; + model6.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.translucent = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model6]; - LLTitleCellModel *model7 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + LLTitleCellModel *model7 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[self LL_hierarchyColorDescription:self.barTintColor]]; + model7.block = ^{ + [weakSelf LL_showColorAlertAndAutomicSetWithKeyPath:@"barTintColor"]; + }; [settings addObject:model7]; - LLTitleCellModel *model8 = [self LL_noneInsetsCellModelWithTitle:@"Background" detailTitle:[self LL_hierarchyImageDescription:self.backgroundImage]]; + LLTitleCellModel *model8 = [[[LLTitleCellModel alloc] initWithTitle:@"Background" detailTitle:[self LL_hierarchyImageDescription:self.backgroundImage]] noneInsets]; [settings addObject:model8]; - LLTitleCellModel *model9 = [self LL_normalInsetsCellModelWithTitle:@"Scope Bar" detailTitle:[self LL_hierarchyImageDescription:self.scopeBarBackgroundImage]]; + LLTitleCellModel *model9 = [[LLTitleCellModel alloc] initWithTitle:@"Scope Bar" detailTitle:[self LL_hierarchyImageDescription:self.scopeBarBackgroundImage]]; [settings addObject:model9]; - LLTitleCellModel *model10 = [self LL_noneInsetsCellModelWithTitle:@"Text Offset" detailTitle:[self LL_hierarchyOffsetDescription:self.searchTextPositionAdjustment]]; + LLTitleCellModel *model10 = [[[LLTitleCellModel alloc] initWithTitle:@"Text Offset" detailTitle:[self LL_hierarchyOffsetDescription:self.searchTextPositionAdjustment]] noneInsets]; [settings addObject:model10]; - LLTitleCellModel *model11 = [self LL_normalInsetsCellModelWithTitle:@"BG Offset" detailTitle:[self LL_hierarchyOffsetDescription:self.searchFieldBackgroundPositionAdjustment]]; + LLTitleCellModel *model11 = [[LLTitleCellModel alloc] initWithTitle:@"BG Offset" detailTitle:[self LL_hierarchyOffsetDescription:self.searchFieldBackgroundPositionAdjustment]]; [settings addObject:model11]; - LLTitleCellModel *model12 = [self LL_noneInsetsCellModelWithTitle:@"Options" detailTitle:[NSString stringWithFormat:@"Shows Search Results Button %@",[self LL_hierarchyBoolDescription:self.showsSearchResultsButton]]]; + LLTitleCellModel *model12 = [[[LLTitleCellModel alloc] initWithTitle:@"Options" detailTitle:@"Shows Search Results Button" flag:self.showsSearchResultsButton] noneInsets]; + model12.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsSearchResultsButton = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model12]; - LLTitleCellModel *model13 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shows Bookmarks Button %@",[self LL_hierarchyBoolDescription:self.showsBookmarkButton]]]; + LLTitleCellModel *model13 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shows Bookmarks Button" flag:self.showsBookmarkButton] noneInsets]; + model13.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsBookmarkButton = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model13]; - LLTitleCellModel *model14 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shows Cancel Button %@",[self LL_hierarchyBoolDescription:self.showsCancelButton]]]; + LLTitleCellModel *model14 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shows Cancel Button" flag:self.showsCancelButton] noneInsets]; + model14.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsCancelButton = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model14]; - LLTitleCellModel *model15 = [self LL_normalInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Shows Scope Bar %@",[self LL_hierarchyBoolDescription:self.showsScopeBar]]]; + LLTitleCellModel *model15 = [[LLTitleCellModel alloc] initWithTitle:nil detailTitle:@"Shows Scope Bar" flag:self.showsScopeBar]; + model15.changePropertyBlock = ^(id _Nullable obj) { + weakSelf.showsScopeBar = [obj boolValue]; + [weakSelf LL_postHierarchyChangeNotification]; + }; [settings addObject:model15]; - LLTitleCellModel *model16 = [self LL_normalInsetsCellModelWithTitle:@"Scope Titles" detailTitle:[self LL_hierarchyObjectDescription:self.scopeButtonTitles]]; + LLTitleCellModel *model16 = [[LLTitleCellModel alloc] initWithTitle:@"Scope Titles" detailTitle:[self LL_hierarchyObjectDescription:self.scopeButtonTitles]]; [settings addObject:model16]; - LLTitleCellModel *model17 = [self LL_noneInsetsCellModelWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]]; + LLTitleCellModel *model17 = [[[LLTitleCellModel alloc] initWithTitle:@"Capitalization" detailTitle:[LLEnumDescription textAutocapitalizationTypeDescription:self.autocapitalizationType]] noneInsets]; + model17.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocapitalizationTypes] currentAction:[LLEnumDescription textAutocapitalizationTypeDescription:weakSelf.autocapitalizationType] completion:^(NSInteger index) { + weakSelf.autocapitalizationType = index; + }]; + }; [settings addObject:model17]; - LLTitleCellModel *model18 = [self LL_noneInsetsCellModelWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]]; + LLTitleCellModel *model18 = [[[LLTitleCellModel alloc] initWithTitle:@"Correction" detailTitle:[LLEnumDescription textAutocorrectionTypeDescription:self.autocorrectionType]] noneInsets]; + model18.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription textAutocorrectionTypes] currentAction:[LLEnumDescription textAutocorrectionTypeDescription:weakSelf.autocorrectionType] completion:^(NSInteger index) { + weakSelf.autocorrectionType = index; + }]; + }; [settings addObject:model18]; - LLTitleCellModel *model19 = [self LL_normalInsetsCellModelWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]]; + LLTitleCellModel *model19 = [[LLTitleCellModel alloc] initWithTitle:@"Keyboard" detailTitle:[LLEnumDescription keyboardTypeDescription:self.keyboardType]]; + model19.block = ^{ + [weakSelf LL_showActionSheetWithActions:[LLEnumDescription keyboardTypes] currentAction:[LLEnumDescription keyboardTypeDescription:weakSelf.keyboardType] completion:^(NSInteger index) { + weakSelf.keyboardType = index; + }]; + }; [settings addObject:model19]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Search Bar" items:settings]; @@ -1382,10 +2509,10 @@ @implementation UIWindow (LL_Hierarchy) - (NSArray *)LL_hierarchyCategoryModels { NSMutableArray *settings = [[NSMutableArray alloc] init]; - LLTitleCellModel *model1 = [self LL_noneInsetsCellModelWithTitle:nil detailTitle:[NSString stringWithFormat:@"Key Window %@",[self LL_hierarchyBoolDescription:self.isKeyWindow]]]; + LLTitleCellModel *model1 = [[[LLTitleCellModel alloc] initWithTitle:nil detailTitle:[NSString stringWithFormat:@"Key Window %@",[self LL_hierarchyBoolDescription:self.isKeyWindow]]] noneInsets]; [settings addObject:model1]; - LLTitleCellModel *model2 = [self LL_normalInsetsCellModelWithTitle:@"Root Controller" detailTitle:[self LL_hierarchyObjectDescription:self.rootViewController]]; + LLTitleCellModel *model2 = [[LLTitleCellModel alloc] initWithTitle:@"Root Controller" detailTitle:[self LL_hierarchyObjectDescription:self.rootViewController]]; [settings addObject:model2]; LLTitleCellCategoryModel *model = [[LLTitleCellCategoryModel alloc] initWithTitle:@"Window" items:settings]; diff --git a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyDetailViewController.m b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyDetailViewController.m index 5edaceaa..491bb5b6 100644 --- a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyDetailViewController.m +++ b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyDetailViewController.m @@ -33,6 +33,7 @@ #import "LLDetailTitleCell.h" #import "UIImage+LL_Utils.h" #import "NSObject+LL_Hierarchy.h" +#import "UIViewController+LL_Utils.h" @interface LLHierarchyDetailViewController () @@ -65,6 +66,8 @@ - (void)viewDidLoad { self.tableView.tableHeaderView = headerView; [self loadData]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveLLHierarchyChangeNotification:) name:LLHierarchyChangeNotificationName object:nil]; } #pragma mark - Over write @@ -84,11 +87,30 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N return cell; } +#pragma mark - NSNotifications +- (void)didReceiveLLHierarchyChangeNotification:(NSNotification *)notification { + [self loadData]; +} + +#pragma mark - Event responses +- (void)segmentedControlValueChanged:(UISegmentedControl *)sender { + [self reloadTableView]; +} + #pragma mark - Primary - (void)loadData { [self.objectDatas removeAllObjects]; NSArray *models = [self.selectView LL_hierarchyCategoryModels]; [self.objectDatas addObjectsFromArray:models]; + + [self.sizeDatas removeAllObjects]; + NSArray *sizeModels = [self.selectView LL_sizeHierarchyCategoryModels]; + [self.sizeDatas addObjectsFromArray:sizeModels]; + + [self reloadTableView]; +} + +- (void)reloadTableView { [self.dataArray removeAllObjects]; if (self.segmentedControl.selectedSegmentIndex == 0) { [self.dataArray addObjectsFromArray:self.objectDatas]; @@ -101,9 +123,10 @@ - (void)loadData { #pragma mark - Getters and setters - (UISegmentedControl *)segmentedControl { if (!_segmentedControl) { - _segmentedControl = [LLFactory getSegmentedControl:nil frame:CGRectMake(kLLGeneralMargin, kLLGeneralMargin, self.view.LL_width - kLLGeneralMargin * 2, 30) items:@[@"Object"]/*@[@"Object", @"Size"]*/]; + _segmentedControl = [LLFactory getSegmentedControl:nil frame:CGRectMake(kLLGeneralMargin, kLLGeneralMargin, self.view.LL_width - kLLGeneralMargin * 2, 30) items:@[@"Object", @"Size"]]; [_segmentedControl setTitleTextAttributes:@{NSForegroundColorAttributeName : [LLThemeManager shared].primaryColor} forState:UIControlStateNormal]; [_segmentedControl setTitleTextAttributes:@{NSForegroundColorAttributeName : [LLThemeManager shared].backgroundColor} forState:UIControlStateSelected]; + [_segmentedControl addTarget:self action:@selector(segmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged]; _segmentedControl.backgroundColor = [LLThemeManager shared].containerColor; _segmentedControl.tintColor = [LLThemeManager shared].primaryColor; #ifdef __IPHONE_13_0 diff --git a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyInfoView.m b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyInfoView.m index 9837ed0b..d7e8bf46 100644 --- a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyInfoView.m +++ b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyInfoView.m @@ -33,6 +33,7 @@ #import "LLToastUtils.h" #import "LLImageNameConfig.h" #import "UIView+LL_Utils.h" +#import "NSObject+LL_Hierarchy.h" @interface LLHierarchyInfoView () @@ -40,6 +41,16 @@ @interface LLHierarchyInfoView () @property (nonatomic, strong) UILabel *contentLabel; +@property (nonatomic, strong) UILabel *frameLabel; + +@property (nonatomic, strong) UILabel *backgroundColorLabel; + +@property (nonatomic, strong) UILabel *textColorLabel; + +@property (nonatomic, strong) UILabel *fontLabel; + +@property (nonatomic, strong) UILabel *tagLabel; + @property (nonatomic, strong) UIView *actionContentView; @property (nonatomic, strong) UIButton *moreButton; @@ -77,41 +88,52 @@ - (void)updateSelectedView:(UIView *)selectedView { NSDictionary *boldAttri = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:17]}; NSDictionary *attri = @{NSFontAttributeName: [UIFont systemFontOfSize:14]}; - NSMutableAttributedString *attribute = [[NSMutableAttributedString alloc] init]; - NSMutableAttributedString *name = [[NSMutableAttributedString alloc] initWithString:@"Name: " attributes:boldAttri]; [name appendAttributedString:[[NSAttributedString alloc] initWithString:NSStringFromClass(view.class) attributes:attri]]; - [attribute appendAttributedString:name]; + self.contentLabel.attributedText = name; - NSMutableAttributedString *frame = [[NSMutableAttributedString alloc] initWithString:@"\nFrame: " attributes:boldAttri]; + NSMutableAttributedString *frame = [[NSMutableAttributedString alloc] initWithString:@"Frame: " attributes:boldAttri]; [frame appendAttributedString:[[NSAttributedString alloc] initWithString:[LLTool stringFromFrame:view.frame] attributes:attri]]; - [attribute appendAttributedString:frame]; + + self.frameLabel.attributedText = frame; if (view.backgroundColor) { - NSMutableAttributedString *color = [[NSMutableAttributedString alloc] initWithString:@"\nBackground: " attributes:boldAttri]; + NSMutableAttributedString *color = [[NSMutableAttributedString alloc] initWithString:@"Background: " attributes:boldAttri]; [color appendAttributedString:[[NSAttributedString alloc] initWithString:[view.backgroundColor LL_description] attributes:attri]]; - [attribute appendAttributedString:color]; + self.backgroundColorLabel.attributedText = color; + } else { + self.backgroundColorLabel.attributedText = nil; } if ([view isKindOfClass:[UILabel class]]) { UILabel *label = (UILabel *)view; - NSMutableAttributedString *font = [[NSMutableAttributedString alloc] initWithString:@"\nText Color: " attributes:boldAttri]; - [font appendAttributedString:[[NSAttributedString alloc] initWithString:[label.textColor LL_description] attributes:attri]]; - [font appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nFont: " attributes:boldAttri]]; + NSMutableAttributedString *textColor = [[NSMutableAttributedString alloc] initWithString:@"Text Color: " attributes:boldAttri]; + [textColor appendAttributedString:[[NSAttributedString alloc] initWithString:[label.textColor LL_description] attributes:attri]]; + self.textColorLabel.attributedText = textColor; + + NSMutableAttributedString *font = [[NSMutableAttributedString alloc] initWithString:@"Font: " attributes:boldAttri]; [font appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%0.2f", label.font.pointSize] attributes:attri]]; - [attribute appendAttributedString:font]; + self.fontLabel.attributedText = font; + } else { + self.textColorLabel.attributedText = nil; + self.fontLabel.attributedText = nil; } if (view.tag != 0) { - NSMutableAttributedString *tag = [[NSMutableAttributedString alloc] initWithString:@"\nTag: " attributes:boldAttri]; + NSMutableAttributedString *tag = [[NSMutableAttributedString alloc] initWithString:@"Tag: " attributes:boldAttri]; [tag appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld",(long)view.tag] attributes:attri]]; - [attribute appendAttributedString:tag]; + self.tagLabel.attributedText = tag; + } else { + self.tagLabel.attributedText = nil; } - self.contentLabel.attributedText = attribute; - [self.contentLabel sizeToFit]; + [self.frameLabel sizeToFit]; + [self.backgroundColorLabel sizeToFit]; + [self.textColorLabel sizeToFit]; + [self.fontLabel sizeToFit]; + [self.tagLabel sizeToFit]; [self updateHeightIfNeeded]; } @@ -127,7 +149,17 @@ - (void)layoutSubviews { self.moreButton.frame = CGRectMake(kLLGeneralMargin, self.parentViewsButton.LL_bottom + kLLGeneralMargin, self.actionContentView.LL_width - kLLGeneralMargin * 2, self.parentViewsButton.LL_height); - self.contentLabel.frame = CGRectMake(kLLGeneralMargin, kLLGeneralMargin, self.closeButton.LL_x - kLLGeneralMargin - kLLGeneralMargin, self.actionContentView.LL_y - kLLGeneralMargin - kLLGeneralMargin); + self.contentLabel.frame = CGRectMake(kLLGeneralMargin, kLLGeneralMargin, self.closeButton.LL_x - kLLGeneralMargin - kLLGeneralMargin, self.contentLabel.LL_height); + + self.frameLabel.frame = CGRectMake(self.contentLabel.LL_x, self.contentLabel.LL_bottom, self.contentLabel.LL_width, self.frameLabel.LL_height); + + self.backgroundColorLabel.frame = CGRectMake(self.contentLabel.LL_x, self.frameLabel.LL_bottom, self.contentLabel.LL_width, self.backgroundColorLabel.LL_height); + + self.textColorLabel.frame = CGRectMake(self.contentLabel.LL_x, self.backgroundColorLabel.LL_bottom, self.contentLabel.LL_width, self.textColorLabel.LL_height); + + self.fontLabel.frame = CGRectMake(self.contentLabel.LL_x, self.textColorLabel.LL_bottom, self.contentLabel.LL_width, self.fontLabel.LL_height); + + self.tagLabel.frame = CGRectMake(self.contentLabel.LL_x, self.fontLabel.LL_bottom, self.contentLabel.LL_width, self.tagLabel.LL_height); } #pragma mark - Over write @@ -136,6 +168,11 @@ - (void)initUI { self.actionContentViewHeight = 80; [self addSubview:self.contentLabel]; + [self addSubview:self.frameLabel]; + [self addSubview:self.backgroundColorLabel]; + [self addSubview:self.textColorLabel]; + [self addSubview:self.fontLabel]; + [self addSubview:self.tagLabel]; [self addSubview:self.actionContentView]; [self.actionContentView addSubview:self.parentViewsButton]; [self.actionContentView addSubview:self.subviewsButton]; @@ -149,9 +186,30 @@ - (void)buttonClicked:(UIButton *)sender { [self.delegate LLHierarchyInfoView:self didSelectAt:sender.tag]; } +- (void)frameLabelTapGestureRecognizer:(UITapGestureRecognizer *)sender { + [self.selectedView LL_showFrameAlertAndAutomicSetWithKeyPath:@"frame"]; +} + +- (void)backgroundColorLabelTapGestureRecognizer:(UITapGestureRecognizer *)sender { + [self.selectedView LL_showColorAlertAndAutomicSetWithKeyPath:@"backgroundColor"]; +} + +- (void)textColorLabelTapGestureRecognizer:(UITapGestureRecognizer *)sender { + [self.selectedView LL_showColorAlertAndAutomicSetWithKeyPath:@"textColor"]; +} + +- (void)fontLabelTapGestureRecognizer:(UITapGestureRecognizer *)sender { + [self.selectedView LL_showFontAlertAndAutomicSetWithKeyPath:@"font"]; +} + +- (void)tagLabelTapGestureRecognizer:(UITapGestureRecognizer *)sender { + [self.selectedView LL_showIntAlertAndAutomicSetWithKeyPath:@"tag"]; +} + #pragma mark - Primary - (void)updateHeightIfNeeded { - CGFloat height = kLLGeneralMargin + MAX(self.contentLabel.LL_height, self.closeButton.LL_height) + kLLGeneralMargin + self.actionContentViewHeight + kLLGeneralMargin; + CGFloat contentHeight = self.contentLabel.LL_height + self.frameLabel.LL_height + self.backgroundColorLabel.LL_height + self.textColorLabel.LL_height + self.fontLabel.LL_height + self.tagLabel.LL_height; + CGFloat height = kLLGeneralMargin + MAX(contentHeight, self.closeButton.LL_height) + kLLGeneralMargin + self.actionContentViewHeight + kLLGeneralMargin; if (height != self.LL_height) { self.LL_height = height; if (!self.isMoved) { @@ -180,6 +238,56 @@ - (UILabel *)contentLabel { return _contentLabel; } +- (UILabel *)frameLabel { + if (!_frameLabel) { + _frameLabel = [LLFactory getLabel:nil frame:CGRectZero text:nil font:14 textColor:[LLThemeManager shared].primaryColor]; + _frameLabel.numberOfLines = 0; + _frameLabel.lineBreakMode = NSLineBreakByCharWrapping; + [_frameLabel LL_addClickListener:self action:@selector(frameLabelTapGestureRecognizer:)]; + } + return _frameLabel; +} + +- (UILabel *)backgroundColorLabel { + if (!_backgroundColorLabel) { + _backgroundColorLabel = [LLFactory getLabel:nil frame:CGRectZero text:nil font:14 textColor:[LLThemeManager shared].primaryColor]; + _backgroundColorLabel.numberOfLines = 0; + _backgroundColorLabel.lineBreakMode = NSLineBreakByCharWrapping; + [_backgroundColorLabel LL_addClickListener:self action:@selector(backgroundColorLabelTapGestureRecognizer:)]; + } + return _backgroundColorLabel; +} + +- (UILabel *)textColorLabel { + if (!_textColorLabel) { + _textColorLabel = [LLFactory getLabel:nil frame:CGRectZero text:nil font:14 textColor:[LLThemeManager shared].primaryColor]; + _textColorLabel.numberOfLines = 0; + _textColorLabel.lineBreakMode = NSLineBreakByCharWrapping; + [_textColorLabel LL_addClickListener:self action:@selector(textColorLabelTapGestureRecognizer:)]; + } + return _textColorLabel; +} + +- (UILabel *)fontLabel { + if (!_fontLabel) { + _fontLabel = [LLFactory getLabel:nil frame:CGRectZero text:nil font:14 textColor:[LLThemeManager shared].primaryColor]; + _fontLabel.numberOfLines = 0; + _fontLabel.lineBreakMode = NSLineBreakByCharWrapping; + [_fontLabel LL_addClickListener:self action:@selector(fontLabelTapGestureRecognizer:)]; + } + return _fontLabel; +} + +- (UILabel *)tagLabel { + if (!_tagLabel) { + _tagLabel = [LLFactory getLabel:nil frame:CGRectZero text:nil font:14 textColor:[LLThemeManager shared].primaryColor]; + _tagLabel.numberOfLines = 0; + _tagLabel.lineBreakMode = NSLineBreakByCharWrapping; + [_tagLabel LL_addClickListener:self action:@selector(tagLabelTapGestureRecognizer:)]; + } + return _tagLabel; +} + - (UIView *)actionContentView { if (!_actionContentView) { _actionContentView = [LLFactory getView]; diff --git a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyViewController.m b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyViewController.m index 61a6fda1..e1d27513 100644 --- a/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyViewController.m +++ b/LLDebugTool/Core/Component/Hierarchy/UserInterface/LLHierarchyViewController.m @@ -35,6 +35,7 @@ #import "LLHierarchyDetailViewController.h" #import "LLNavigationController.h" #import "LLTool.h" +#import "UIViewController+LL_Utils.h" @interface LLHierarchyViewController () @@ -234,7 +235,7 @@ - (void)showParentSheet:(UIView *)selectView { [actions addObject:NSStringFromClass(view.class)]; } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Parent Views" actions:actions currentAction:nil completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Parent Views" actions:actions currentAction:nil completion:^(NSInteger index) { [weakSelf setNewSelectView:parentViews[index]]; }]; } @@ -246,7 +247,7 @@ - (void)showSubviewSheet:(UIView *)selectView { [actions addObject:NSStringFromClass(view.class)]; } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Subviews" actions:actions currentAction:nil completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Subviews" actions:actions currentAction:nil completion:^(NSInteger index) { [weakSelf setNewSelectView:subviews[index]]; }]; } diff --git a/LLDebugTool/Core/Component/Html/LLHtmlComponent.m b/LLDebugTool/Core/Component/Html/LLHtmlComponent.m index 75299e93..3bfb07d2 100644 --- a/LLDebugTool/Core/Component/Html/LLHtmlComponent.m +++ b/LLDebugTool/Core/Component/Html/LLHtmlComponent.m @@ -22,11 +22,12 @@ #import "LLHtmlComponent.h" #import "LLWindowManager.h" #import "LLNavigationController.h" +#import "LLHtmlConfigViewController.h" @implementation LLHtmlComponent - (void)componentDidLoad:(NSDictionary *)data { - LLHtmlWindow *window = [LLWindowManager htmlWindow]; + if (data[kLLComponentWindowRootViewControllerKey]) { Class rootViewControllerClass = NSClassFromString(data[kLLComponentWindowRootViewControllerKey]); if (rootViewControllerClass != nil) { @@ -37,10 +38,20 @@ - (void)componentDidLoad:(NSDictionary *)data { [viewController setValue:value forKey:key]; } LLNavigationController *nav = [[LLNavigationController alloc] initWithRootViewController:viewController]; + LLHtmlWindow *window = [LLWindowManager htmlWindow]; window.rootViewController = nav; + [[LLWindowManager shared] showWindow:window animated:YES]; + return; } } - [[LLWindowManager shared] showWindow:window animated:YES]; + + LLBaseWindow *window = [[LLWindowManager shared] visiableWindow]; + if ([window isKindOfClass:[LLFunctionWindow class]]) { + LLNavigationController *nav = (LLNavigationController *)window.rootViewController; + [nav pushViewController:[[LLHtmlConfigViewController alloc] init] animated:YES]; + } else { + [[LLWindowManager shared] showWindow:[LLWindowManager htmlWindow] animated:YES]; + } } @end diff --git a/LLDebugTool/Core/Component/Html/UserInterface/LLHtmlConfigViewController.m b/LLDebugTool/Core/Component/Html/UserInterface/LLHtmlConfigViewController.m index 6af81d6f..9636e710 100644 --- a/LLDebugTool/Core/Component/Html/UserInterface/LLHtmlConfigViewController.m +++ b/LLDebugTool/Core/Component/Html/UserInterface/LLHtmlConfigViewController.m @@ -19,6 +19,7 @@ #import "LLHtmlUIWebViewController.h" #import "LLHtmlWkWebViewController.h" #import "LLConfig.h" +#import "UIViewController+LL_Utils.h" #import @interface LLHtmlConfigViewController () @@ -41,6 +42,7 @@ - (void)viewDidLoad { } - (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; if ([self.headerTextField isFirstResponder]) { [self.headerTextField resignFirstResponder]; } @@ -112,7 +114,7 @@ - (void)loadData { } - (LLTitleCellModel *)getWebViewStyleModel { - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitleSelector:self.webViewClass]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:self.webViewClass]; __weak typeof(self) weakSelf = self; model.block = ^{ [weakSelf showWebViewClassAlert]; @@ -128,7 +130,7 @@ - (void)showWebViewClassAlert { [actions addObject:NSStringFromClass([UIWebView class])]; #pragma clang diagnostic pop __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Web View Style" actions:actions currentAction:self.webViewClass completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Web View Style" actions:actions currentAction:self.webViewClass completion:^(NSInteger index) { [weakSelf setNewWebViewClass:actions[index]]; }]; } diff --git a/LLDebugTool/Core/Component/Log/UserInterface/LLLogViewController.m b/LLDebugTool/Core/Component/Log/UserInterface/LLLogViewController.m index 1e4f50ec..54a8b300 100644 --- a/LLDebugTool/Core/Component/Log/UserInterface/LLLogViewController.m +++ b/LLDebugTool/Core/Component/Log/UserInterface/LLLogViewController.m @@ -34,6 +34,7 @@ #import "LLToastUtils.h" #import "UIView+LL_Utils.h" #import "LLConst.h" +#import "UIViewController+LL_Utils.h" static NSString *const kLogCellID = @"LLLogCell"; @@ -123,7 +124,7 @@ - (void)deleteFilesWithIndexPaths:(NSArray *)indexPaths { if (result) { [weakSelf updateAfterDelete:models indexPaths:indexPaths]; } else { - [weakSelf showAlertControllerWithMessage:@"Remove log model fail" handler:^(NSInteger action) { + [weakSelf LL_showAlertControllerWithMessage:@"Remove log model fail" handler:^(NSInteger action) { if (action == 1) { [weakSelf loadData]; } diff --git a/LLDebugTool/Core/Component/Network/UserInterface/LLNetworkViewController.m b/LLDebugTool/Core/Component/Network/UserInterface/LLNetworkViewController.m index e820699d..fd4e848b 100644 --- a/LLDebugTool/Core/Component/Network/UserInterface/LLNetworkViewController.m +++ b/LLDebugTool/Core/Component/Network/UserInterface/LLNetworkViewController.m @@ -36,6 +36,7 @@ #import "LLToastUtils.h" #import "UIView+LL_Utils.h" #import "LLConst.h" +#import "UIViewController+LL_Utils.h" static NSString *const kNetworkCellID = @"NetworkCellID"; @@ -120,7 +121,7 @@ - (void)deleteFilesWithIndexPaths:(NSArray *)indexPaths { [weakSelf.searchDataArray removeObjectsInArray:models]; [weakSelf.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; } else { - [weakSelf showAlertControllerWithMessage:@"Remove network model fail" handler:^(NSInteger action) { + [weakSelf LL_showAlertControllerWithMessage:@"Remove network model fail" handler:^(NSInteger action) { if (action == 1) { [weakSelf loadData]; } diff --git a/LLDebugTool/Core/Component/Sandbox/UserInterface/LLSandboxViewController.m b/LLDebugTool/Core/Component/Sandbox/UserInterface/LLSandboxViewController.m index 1c5d8441..c45409a5 100644 --- a/LLDebugTool/Core/Component/Sandbox/UserInterface/LLSandboxViewController.m +++ b/LLDebugTool/Core/Component/Sandbox/UserInterface/LLSandboxViewController.m @@ -29,6 +29,7 @@ #import "LLImageNameConfig.h" #import "LLUITableViewLongPressGestureRecognizerDelegate.h" #import "LLToastUtils.h" +#import "UIViewController+LL_Utils.h" static NSString *const kSandboxCellID = @"LLSandboxCell"; @@ -115,7 +116,7 @@ - (BOOL)deleteFile:(LLSandboxModel *)model { if ([[NSFileManager defaultManager] fileExistsAtPath:model.filePath]) { BOOL ret = [[NSFileManager defaultManager] removeItemAtPath:model.filePath error:&error]; if (!ret) { - [self showAlertControllerWithMessage:[NSString stringWithFormat:@"Delete file fail\nFilePath:%@\nError:%@",model.filePath,error.localizedDescription] handler:nil]; + [self LL_showAlertControllerWithMessage:[NSString stringWithFormat:@"Delete file fail\nFilePath:%@\nError:%@",model.filePath,error.localizedDescription] handler:nil]; } return ret; } diff --git a/LLDebugTool/Core/Component/Setting/UserInterface/LLSettingViewController.m b/LLDebugTool/Core/Component/Setting/UserInterface/LLSettingViewController.m index 87a64647..a456e52a 100644 --- a/LLDebugTool/Core/Component/Setting/UserInterface/LLSettingViewController.m +++ b/LLDebugTool/Core/Component/Setting/UserInterface/LLSettingViewController.m @@ -35,6 +35,7 @@ #import "LLImageNameConfig.h" #import "LLConst.h" #import "LLTitleSliderCell.h" +#import "UIViewController+LL_Utils.h" @interface LLSettingViewController () @@ -103,7 +104,7 @@ - (void)setUpUI { - (LLTitleCellModel *)getDoubleClickComponentModel { __weak typeof(self) weakSelf = self; - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Double Click" detailTitleSelector:[LLConfigHelper doubleClickComponentDescription]]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Double Click" detailTitle:[LLConfigHelper doubleClickComponentDescription]]; model.block = ^{ [weakSelf showDoubleClickAlert]; }; @@ -119,7 +120,7 @@ - (void)showDoubleClickAlert { } } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Double Click Event" actions:actions currentAction:[LLConfigHelper doubleClickComponentDescription] completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Double Click Event" actions:actions currentAction:[LLConfigHelper doubleClickComponentDescription] completion:^(NSInteger index) { [weakSelf setNewDoubleClick:index + LLDebugToolActionSetting]; }]; } @@ -146,7 +147,7 @@ - (void)setNewShakeToHide:(BOOL)isShakeToHide { - (LLTitleCellModel *)getColorStyleModel { __weak typeof(self) weakSelf = self; - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitleSelector:[LLConfigHelper colorStyleDetailDescription]]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLConfigHelper colorStyleDetailDescription]]; model.block = ^{ [weakSelf showColorStyleAlert]; }; @@ -162,7 +163,7 @@ - (void)showColorStyleAlert { } } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Color Style" actions:actions currentAction:[LLConfigHelper colorStyleDescription] completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Color Style" actions:actions currentAction:[LLConfigHelper colorStyleDescription] completion:^(NSInteger index) { [weakSelf setNewColorStyle:index]; }]; } @@ -181,7 +182,7 @@ - (void)setNewColorStyle:(LLConfigColorStyle)style { } - (LLTitleCellModel *)getStatusBarStyleModel { - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Status Bar" detailTitleSelector:[LLConfigHelper statusBarStyleDescription]]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Status Bar" detailTitle:[LLConfigHelper statusBarStyleDescription]]; __weak typeof(self) weakSelf = self; model.block = ^{ [weakSelf showStatusBarStyleAlert]; @@ -203,7 +204,7 @@ - (void)showStatusBarStyleAlert { } } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Status Bar Style" actions:actions currentAction:[LLConfigHelper statusBarStyleDescription] completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Status Bar Style" actions:actions currentAction:[LLConfigHelper statusBarStyleDescription] completion:^(NSInteger index) { [weakSelf setNewStatusBarStyle:index]; }]; } @@ -227,7 +228,7 @@ - (void)setNewStatusBarStyle:(UIStatusBarStyle)style { - (LLTitleCellModel *)getEntryWindowStyleModel { __weak typeof(self) weakSelf = self; - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitleSelector:[LLConfigHelper entryWindowStyleDescription]]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLConfigHelper entryWindowStyleDescription]]; model.block = ^{ [weakSelf showEntryWindowStyleAlert]; }; @@ -248,7 +249,7 @@ - (void)showEntryWindowStyleAlert { } } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Entry Window Style" actions:actions currentAction:[LLConfigHelper entryWindowStyleDescription] completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Entry Window Style" actions:actions currentAction:[LLConfigHelper entryWindowStyleDescription] completion:^(NSInteger index) { [weakSelf setNewEntryWindowStyle:index]; }]; } @@ -278,7 +279,7 @@ - (void)setNewShrinkToEdgeWhenInactive:(BOOL)isShrinkToEdgeWhenInactive { } - (LLTitleCellModel *)getLogStyleModel { - LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitleSelector:[LLConfigHelper logStyleDescription]]; + LLTitleCellModel *model = [[LLTitleCellModel alloc] initWithTitle:@"Style" detailTitle:[LLConfigHelper logStyleDescription]]; __weak typeof(self) weakSelf = self; model.block = ^{ [weakSelf showLogStyleAlert]; @@ -295,7 +296,7 @@ - (void)showLogStyleAlert { } } __weak typeof(self) weakSelf = self; - [self showActionSheetWithTitle:@"Log Style" actions:actions currentAction:[LLConfigHelper logStyleDescription] completion:^(NSInteger index) { + [self LL_showActionSheetWithTitle:@"Log Style" actions:actions currentAction:[LLConfigHelper logStyleDescription] completion:^(NSInteger index) { [weakSelf setNewLogStyle:index]; }]; } diff --git a/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.h b/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.h index 0fab6aad..165dfb85 100644 --- a/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.h +++ b/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.h @@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN + (UIColor *)LL_colorWithHex:(NSString *)hex; ++ (UIColor *)LL_colorWithHex:(NSString *)hex error:(BOOL *_Nullable)error; + - (NSArray *)LL_RGBA; - (NSString *)LL_HexString; diff --git a/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.m b/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.m index 390c602e..9efaca4b 100644 --- a/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.m +++ b/LLDebugTool/Core/Others/Category/UIColor/UIColor+LL_Utils.m @@ -26,7 +26,14 @@ @implementation UIColor (LL_Utils) + (UIColor *)LL_colorWithHex:(NSString *)hex { + return [self LL_colorWithHex:hex error:nil]; +} + ++ (UIColor *)LL_colorWithHex:(NSString *)hex error:(BOOL *)error { if ([hex length] < 6){//长度不合法 + if (error) { + *error = YES; + } return [UIColor blackColor]; } NSString *tempString = [hex lowercaseString]; @@ -36,6 +43,9 @@ + (UIColor *)LL_colorWithHex:(NSString *)hex { tempString = [tempString substringFromIndex:1]; } if ([tempString length] != 6){ + if (error) { + *error = YES; + } return [UIColor blackColor]; } @@ -54,6 +64,9 @@ + (UIColor *)LL_colorWithHex:(NSString *)hex { [[NSScanner scannerWithString:rString] scanHexInt:&r]; [[NSScanner scannerWithString:gString] scanHexInt:&g]; [[NSScanner scannerWithString:bString] scanHexInt:&b]; + if (error) { + *error = NO; + } return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) diff --git a/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.h b/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.h index 7e5b2b39..85dc801f 100644 --- a/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.h +++ b/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.h @@ -63,7 +63,7 @@ NS_ASSUME_NONNULL_BEGIN - (UIView *_Nullable)LL_bottomView; -- (void)LL_AddClickListener:(id)target action:(SEL)action; +- (void)LL_addClickListener:(id)target action:(SEL)action; - (UIImage *)LL_convertViewToImage; diff --git a/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.m b/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.m index cc19a8e5..78c8bfd7 100644 --- a/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.m +++ b/LLDebugTool/Core/Others/Category/UIView/UIView+LL_Utils.m @@ -191,7 +191,7 @@ - (UIView *_Nullable)LL_bottomView { return view; } -- (void)LL_AddClickListener:(id)target action:(SEL)action { +- (void)LL_addClickListener:(id)target action:(SEL)action { UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:target action:action]; [self addGestureRecognizer:tap]; self.userInteractionEnabled = YES; diff --git a/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.h b/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.h index 81353fef..f709809e 100644 --- a/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.h +++ b/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.h @@ -31,6 +31,12 @@ NS_ASSUME_NONNULL_BEGIN - (UIButton *)LL_navigationButtonWithTitle:(NSString *_Nullable)title imageName:(NSString *_Nullable)imageName target:(id _Nullable)target action:(SEL _Nullable)action; +- (void)LL_showAlertControllerWithMessage:(NSString *)message handler:(nullable void (^)(NSInteger action))handler; + +- (void)LL_showActionSheetWithTitle:(NSString *)title actions:(NSArray *)actions currentAction:(nullable NSString *)currentAction completion:(nullable void (^)(NSInteger index))completion; + +- (void)LL_showTextFieldAlertControllerWithMessage:(NSString *)message text:(nullable NSString *)text handler:(nullable void (^)(NSString * _Nullable))handler; + @end NS_ASSUME_NONNULL_END diff --git a/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.m b/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.m index e94701df..14dd7073 100644 --- a/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.m +++ b/LLDebugTool/Core/Others/Category/UIViewController/UIViewController+LL_Utils.m @@ -25,6 +25,7 @@ #import "LLFactory.h" #import "LLThemeManager.h" #import "UIImage+LL_Utils.h" +#import "LLImageNameConfig.h" @implementation UIViewController (LL_Utils) @@ -58,4 +59,55 @@ - (UIButton *)LL_navigationButtonWithTitle:(NSString *_Nullable)title imageName: return btn; } +- (void)LL_showAlertControllerWithMessage:(NSString *)message handler:(void (^)(NSInteger action))handler { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Note" message:message preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { + if (handler) { + handler(0); + } + }]; + UIAlertAction *confirm = [UIAlertAction actionWithTitle:@"Confirm" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) { + if (handler) { + handler(1); + } + }]; + [alert addAction:cancel]; + [alert addAction:confirm]; + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)LL_showActionSheetWithTitle:(NSString *)title actions:(NSArray *)actions currentAction:(NSString *)currentAction completion:(void (^)(NSInteger index))completion { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:title preferredStyle:UIAlertControllerStyleActionSheet]; + for (NSInteger i = 0; i < actions.count; i++) { + NSString *actionTitle = actions[i]; + __block NSInteger index = i; + UIAlertAction *action = [UIAlertAction actionWithTitle:actionTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + if (completion) { + completion(index); + } + }]; + if (currentAction && [actionTitle isEqualToString:currentAction]) { + action.enabled = NO; + [action setValue:[UIImage LL_imageNamed:kSelectImageName] forKey:@"image"]; + } + [alert addAction:action]; + } + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)LL_showTextFieldAlertControllerWithMessage:(NSString *)message text:(nullable NSString *)text handler:(nullable void (^)(NSString * _Nullable))handler { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert]; + [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + textField.text = text; + }]; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Confirm" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + if (handler) { + handler(alert.textFields.firstObject.text); + } + }]]; + [self presentViewController:alert animated:YES completion:nil]; +} + @end diff --git a/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.h b/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.h index 4278aca5..01c189d1 100644 --- a/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.h +++ b/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.h @@ -33,16 +33,6 @@ NS_ASSUME_NONNULL_BEGIN /// Right navigation item's custom view. @property (nonatomic, strong, nullable) UIButton *rightNavigationButton; -/** - * Simple alert. - */ -- (void)showAlertControllerWithMessage:(NSString *_Nullable)message handler:(void (^_Nullable)(NSInteger action))handler; - -/** - Simple sheet. - */ -- (void)showActionSheetWithTitle:(NSString *)title actions:(NSArray *)actions currentAction:(NSString *_Nullable)currentAction completion:(void (^ _Nullable)(NSInteger index))completion; - /** * Left navigation item action. */ diff --git a/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.m b/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.m index 3824b96a..f7676d52 100644 --- a/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.m +++ b/LLDebugTool/Core/Others/CommonUI/Base/LLBaseViewController.m @@ -49,43 +49,6 @@ - (void)dealloc { } #pragma mark - Public -- (void)showAlertControllerWithMessage:(NSString *)message handler:(void (^)(NSInteger action))handler { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Note" message:message preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - if (handler) { - handler(0); - } - }]; - UIAlertAction *confirm = [UIAlertAction actionWithTitle:@"Confirm" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) { - if (handler) { - handler(1); - } - }]; - [alert addAction:cancel]; - [alert addAction:confirm]; - [self presentViewController:alert animated:YES completion:nil]; -} - -- (void)showActionSheetWithTitle:(NSString *)title actions:(NSArray *)actions currentAction:(NSString *)currentAction completion:(void (^)(NSInteger index))completion { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:title preferredStyle:UIAlertControllerStyleActionSheet]; - for (NSInteger i = 0; i < actions.count; i++) { - NSString *actionTitle = actions[i]; - __block NSInteger index = i; - UIAlertAction *action = [UIAlertAction actionWithTitle:actionTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - if (completion) { - completion(index); - } - }]; - if (currentAction && [actionTitle isEqualToString:currentAction]) { - action.enabled = NO; - [action setValue:[UIImage LL_imageNamed:kSelectImageName] forKey:@"image"]; - } - [alert addAction:action]; - } - [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; - [self presentViewController:alert animated:YES completion:nil]; -} - - (void)leftItemClick:(UIButton *)sender { } diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.h b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.h index 069f69cd..a16d403d 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.h +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.h @@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) UILabel *detailLabel; +@property (nonatomic, strong, readonly) MASConstraint *detailLabelRightCons; + @end NS_ASSUME_NONNULL_END diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.m b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.m index 6d7f291b..02bf966d 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.m +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLDetailTitleCell.m @@ -31,6 +31,8 @@ @interface LLDetailTitleCell () @property (nonatomic, strong) UILabel *detailLabel; +@property (nonatomic, strong) MASConstraint *detailLabelRightCons; + @end @implementation LLDetailTitleCell @@ -44,7 +46,7 @@ - (void)initUI { [self.titleLabelBottomCons uninstall]; [self.detailLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.mas_equalTo(-kLLGeneralMargin); + self.detailLabelRightCons = make.right.mas_equalTo(-kLLGeneralMargin); make.top.mas_equalTo(kLLGeneralMargin); make.bottom.mas_equalTo(-kLLGeneralMargin); make.left.equalTo(self.titleLabel.mas_right).offset(kLLGeneralMargin / 2.0); diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.h b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.h index 82ce518c..d6a96e3c 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.h +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.h @@ -59,16 +59,18 @@ typedef void(^LLSettingModelChangePropertyBlock)(__nullable id obj); // LLTitleSwitchCell - (instancetype)initWithTitle:(NSString *_Nullable)title flag:(BOOL)flag; +- (instancetype)initWithTitle:(NSString *_Nullable)title detailTitle:(NSString *_Nullable)detailTitle flag:(BOOL)flag; // LLDetailTitleCell - (instancetype)initWithTitle:(NSString *_Nullable)title detailTitle:(NSString *_Nullable)detailTitle; -// LLDetailTitleSelectorCell -- (instancetype)initWithTitle:(NSString *_Nullable)title detailTitleSelector:(NSString *_Nullable)detailTitle; - // LLTitleSliderCell - (instancetype)initWithTitle:(NSString *_Nullable)title value:(CGFloat)value minValue:(CGFloat)minValue maxValue:(CGFloat)maxValue; +- (LLTitleCellModel *)normalInsets; + +- (LLTitleCellModel *)noneInsets; + @end NS_ASSUME_NONNULL_END diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.m b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.m index e46e34bc..a4d5eb02 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.m +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleCellModel.m @@ -27,12 +27,18 @@ #import "LLTitleSliderCell.h" #import "LLDetailTitleCell.h" #import "LLConst.h" +#import "LLMacros.h" @implementation LLTitleCellModel - (instancetype)initWithTitle:(NSString *)title flag:(BOOL)flag { + return [self initWithTitle:title detailTitle:nil flag:flag]; +} + +- (instancetype)initWithTitle:(NSString *_Nullable)title detailTitle:(NSString *_Nullable)detailTitle flag:(BOOL)flag { if (self = [super init]) { _title = [title copy]; + _detailTitle = [detailTitle copy]; _flag = flag; _cellClass = NSStringFromClass(LLTitleSwitchCell.class); _separatorInsets = UIEdgeInsetsMake(0, kLLGeneralMargin, 0, 0); @@ -50,16 +56,6 @@ - (instancetype)initWithTitle:(NSString *)title detailTitle:(NSString *)detailTi return self; } -- (instancetype)initWithTitle:(NSString *)title detailTitleSelector:(NSString *)detailTitle { - if (self = [super init]) { - _title = [title copy]; - _detailTitle = [detailTitle copy]; - _cellClass = NSStringFromClass(LLDetailTitleSelectorCell.class); - _separatorInsets = UIEdgeInsetsMake(0, kLLGeneralMargin, 0, 0); - } - return self; -} - - (instancetype)initWithTitle:(NSString *)title value:(CGFloat)value minValue:(CGFloat)minValue maxValue:(CGFloat)maxValue { if (self = [super init]) { _title = [title copy]; @@ -72,4 +68,21 @@ - (instancetype)initWithTitle:(NSString *)title value:(CGFloat)value minValue:(C return self; } +- (LLTitleCellModel *)normalInsets { + self.separatorInsets = UIEdgeInsetsMake(0, kLLGeneralMargin, 0, 0); + return self; +} + +- (LLTitleCellModel *)noneInsets { + self.separatorInsets = UIEdgeInsetsMake(0, LL_SCREEN_WIDTH, 0, 0); + return self; +} + +- (void)setBlock:(LLSettingModelBlock)block { + if (_block != block) { + _block = [block copy]; + _cellClass = NSStringFromClass(block ? LLDetailTitleSelectorCell.class : LLDetailTitleCell.class); + } +} + @end diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.h b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.h index 2cd54dab..db37fa9b 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.h +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.h @@ -21,12 +21,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#import "LLTitleCell.h" -#import "LLTitleCellModel.h" +#import "LLDetailTitleCell.h" NS_ASSUME_NONNULL_BEGIN -@interface LLTitleSwitchCell : LLTitleCell +@interface LLTitleSwitchCell : LLDetailTitleCell @end diff --git a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.m b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.m index f269b524..92c14364 100644 --- a/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.m +++ b/LLDebugTool/Core/Others/CommonUI/View/TitleCell/LLTitleSwitchCell.m @@ -40,10 +40,13 @@ - (void)initUI { [super initUI]; [self.contentView addSubview:self.swit]; + [self.detailLabelRightCons uninstall]; + [self.swit mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.detailLabel.mas_right).offset(kLLGeneralMargin / 2.0); make.right.mas_equalTo(-kLLGeneralMargin); - make.top.mas_equalTo(kLLGeneralMargin); - make.bottom.mas_equalTo(-kLLGeneralMargin); + make.centerY.equalTo(self.contentView); + make.size.mas_equalTo(CGSizeMake(51, 31)); }]; } diff --git a/LLDebugTool/Core/Others/CommonUI/ViewController/EditTableViewController/LLEditTableViewController.m b/LLDebugTool/Core/Others/CommonUI/ViewController/EditTableViewController/LLEditTableViewController.m index 5e040677..807f5e51 100644 --- a/LLDebugTool/Core/Others/CommonUI/ViewController/EditTableViewController/LLEditTableViewController.m +++ b/LLDebugTool/Core/Others/CommonUI/ViewController/EditTableViewController/LLEditTableViewController.m @@ -30,6 +30,7 @@ #import "LLTableViewSelectableModel.h" #import "LLConst.h" #import "UIView+LL_Utils.h" +#import "UIViewController+LL_Utils.h" @interface LLEditTableViewController () @@ -206,7 +207,7 @@ - (void)deleteItemClick:(UIBarButtonItem *)sender { - (void)showDeleteAlertWithIndexPaths:(NSArray *)indexPaths { if (indexPaths.count) { - [self showAlertControllerWithMessage:[NSString stringWithFormat:@"Sure to delete these %ld items?", (long)indexPaths.count] handler:^(NSInteger action) { + [self LL_showAlertControllerWithMessage:[NSString stringWithFormat:@"Sure to delete these %ld items?", (long)indexPaths.count] handler:^(NSInteger action) { if (action == 1) { [self deleteFilesWithIndexPaths:indexPaths]; } diff --git a/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.h b/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.h index d2d7cb09..07ae7538 100644 --- a/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.h +++ b/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.h @@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *_Nullable)lineBreakModeDescription:(NSLineBreakMode)mode; ++ (NSArray *)lineBreaks; + + (NSString *_Nullable)userInterfaceStyleDescription:(UIUserInterfaceStyle)style API_AVAILABLE(ios(12.0)); + (NSString *_Nullable)userInterfaceSizeClassDescription:(UIUserInterfaceSizeClass)sizeClass; @@ -38,58 +40,112 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *_Nullable)viewContentModeDescription:(UIViewContentMode)mode; ++ (NSArray *)viewContentModeDescriptions; + + (NSString *_Nullable)textAlignmentDescription:(NSTextAlignment)textAlignment; ++ (NSArray *)textAlignments; + + (NSString *_Nullable)baselineAdjustmentDescription:(UIBaselineAdjustment)baselineAdjustment; ++ (NSArray *)baselineAdjustments; + + (NSString *_Nullable)controlContentVerticalAlignmentDescription:(UIControlContentVerticalAlignment)contentVerticalAlignment; ++ (NSArray *)controlContentVerticalAlignments; + + (NSString *_Nullable)controlContentHorizontalAlignmentDescription:(UIControlContentHorizontalAlignment)contentHorizontalAlignment; ++ (NSArray *)controlContentHorizontalAlignments; + + (NSString *_Nullable)buttonTypeDescription:(UIButtonType)buttonType; + (NSString *_Nullable)controlStateDescription:(UIControlState)state; + (NSString *_Nullable)textBorderStyleDescription:(UITextBorderStyle)style; ++ (NSArray *)textBorderStyles; + + (NSString *_Nullable)textFieldViewModeDescription:(UITextFieldViewMode)mode; ++ (NSArray *)textFieldViewModes; + + (NSString *_Nullable)textAutocapitalizationTypeDescription:(UITextAutocapitalizationType)type; ++ (NSArray *)textAutocapitalizationTypes; + + (NSString *_Nullable)textAutocorrectionTypeDescription:(UITextAutocorrectionType)type; ++ (NSArray *)textAutocorrectionTypes; + + (NSString *_Nullable)keyboardTypeDescription:(UIKeyboardType)type; ++ (NSArray *)keyboardTypes; + + (NSString *_Nullable)keyboardAppearanceDescription:(UIKeyboardAppearance)appearance; ++ (NSArray *)keyboardAppearances; + + (NSString *_Nullable)returnKeyTypeDescription:(UIReturnKeyType)type; ++ (NSArray *)returnKeyTypes; + + (NSString *_Nullable)activityIndicatorViewStyleDescription:(UIActivityIndicatorViewStyle)style; ++ (NSArray *)activityIndicatorViewStyles; + + (NSString *_Nullable)progressViewStyleDescription:(UIProgressViewStyle)style; ++ (NSArray *)progressViewStyles; + + (NSString *_Nullable)scrollViewIndicatorStyleDescription:(UIScrollViewIndicatorStyle)style; ++ (NSArray *)scrollViewIndicatorStyles; + + (NSString *_Nullable)scrollViewKeyboardDismissModeDescription:(UIScrollViewKeyboardDismissMode)mode; ++ (NSArray *)scrollViewKeyboardDismissModes; + + (NSString *_Nullable)tableViewStyleDescription:(UITableViewStyle)style; + (NSString *_Nullable)tableViewCellSeparatorStyleDescription:(UITableViewCellSeparatorStyle)style; ++ (NSArray *)tableViewCellSeparatorStyles; + + (NSString *_Nullable)tableViewSeparatorInsetReferenceDescription:(UITableViewSeparatorInsetReference)reference API_AVAILABLE(ios(11.0)); ++ (NSArray *)tableViewSeparatorInsetReferences API_AVAILABLE(ios(11.0)); + + (NSString *_Nullable)tableViewCellSelectionStyleDescription:(UITableViewCellSelectionStyle)style; ++ (NSArray *)tableViewCellSelectionStyles; + + (NSString *_Nullable)tableViewCellAccessoryTypeDescription:(UITableViewCellAccessoryType)type; ++ (NSArray *)tableViewCellAccessoryTypes; + + (NSString *_Nullable)datePickerModeDescription:(UIDatePickerMode)mode; ++ (NSArray *)datePickerModes; + + (NSString *_Nullable)barStyleDescription:(UIBarStyle)style; ++ (NSArray *)barStyles; + + (NSString *_Nullable)searchBarStyleDescription:(UISearchBarStyle)style; ++ (NSArray *)searchBarStyles; + + (NSString *_Nullable)tabBarItemPositioningDescription:(UITabBarItemPositioning)positioning; ++ (NSArray *)tabBarItemPositionings; + ++ (NSString *_Nullable)layoutAttributeDescription:(NSLayoutAttribute)attribute; + ++ (NSArray *)layoutAttributes; + ++ (NSString *_Nullable)layoutRelationDescription:(NSLayoutRelation)relation; + @end NS_ASSUME_NONNULL_END diff --git a/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.m b/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.m index d4869cd4..fc719250 100644 --- a/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.m +++ b/LLDebugTool/Core/Others/EnumDescription/LLEnumDescription.m @@ -42,7 +42,18 @@ + (NSString *)lineBreakModeDescription:(NSLineBreakMode)mode { return nil; } -+ (NSString *_Nullable)userInterfaceStyleDescription:(UIUserInterfaceStyle)style { ++ (NSArray *)lineBreaks { + NSMutableArray *breaks = [[NSMutableArray alloc] init]; + for (NSLineBreakMode i = NSLineBreakByWordWrapping; i <= NSLineBreakByTruncatingMiddle; i++) { + NSString *lineBreak = [self lineBreakModeDescription:i]; + if (lineBreak) { + [breaks addObject:lineBreak]; + } + } + return [breaks copy]; +} + ++ (NSString *)userInterfaceStyleDescription:(UIUserInterfaceStyle)style { switch (style) { case UIUserInterfaceStyleUnspecified: return @"Unspecified"; @@ -54,7 +65,7 @@ + (NSString *_Nullable)userInterfaceStyleDescription:(UIUserInterfaceStyle)style return nil; } -+ (NSString *_Nullable)userInterfaceSizeClassDescription:(UIUserInterfaceSizeClass)sizeClass { ++ (NSString *)userInterfaceSizeClassDescription:(UIUserInterfaceSizeClass)sizeClass { switch (sizeClass) { case UIUserInterfaceSizeClassUnspecified: return @"Unspecified"; @@ -66,7 +77,7 @@ + (NSString *_Nullable)userInterfaceSizeClassDescription:(UIUserInterfaceSizeCla return nil; } -+ (NSString *_Nullable)traitEnvironmentLayoutDirectionDescription:(UITraitEnvironmentLayoutDirection)direction { ++ (NSString *)traitEnvironmentLayoutDirectionDescription:(UITraitEnvironmentLayoutDirection)direction { switch (direction) { case UITraitEnvironmentLayoutDirectionUnspecified: return @"Unspecified"; @@ -78,7 +89,7 @@ + (NSString *_Nullable)traitEnvironmentLayoutDirectionDescription:(UITraitEnviro return nil; } -+ (NSString *_Nullable)viewContentModeDescription:(UIViewContentMode)mode { ++ (NSString *)viewContentModeDescription:(UIViewContentMode)mode { switch (mode) { case UIViewContentModeScaleToFill: return @"ScaleToFill"; @@ -110,6 +121,17 @@ + (NSString *_Nullable)viewContentModeDescription:(UIViewContentMode)mode { return nil; } ++ (NSArray *)viewContentModeDescriptions { + NSMutableArray *descriptions = [[NSMutableArray alloc] init]; + for (UIViewContentMode i = UIViewContentModeScaleToFill; i <= UIViewContentModeBottomRight; i++) { + NSString *description = [self viewContentModeDescription:i]; + if (description) { + [descriptions addObject:description]; + } + } + return [descriptions copy]; +} + + (NSString *)textAlignmentDescription:(NSTextAlignment)textAlignment { switch (textAlignment) { case NSTextAlignmentLeft: @@ -126,6 +148,17 @@ + (NSString *)textAlignmentDescription:(NSTextAlignment)textAlignment { return nil; } ++ (NSArray *)textAlignments { + NSMutableArray *alignments = [[NSMutableArray alloc] init]; + for (NSTextAlignment i = NSTextAlignmentLeft; i <= NSTextAlignmentNatural; i++) { + NSString *alignment = [self textAlignmentDescription:i]; + if (alignment) { + [alignments addObject:alignment]; + } + } + return [alignments copy]; +} + + (NSString *)baselineAdjustmentDescription:(UIBaselineAdjustment)baselineAdjustment { switch (baselineAdjustment) { case UIBaselineAdjustmentAlignBaselines: @@ -138,6 +171,17 @@ + (NSString *)baselineAdjustmentDescription:(UIBaselineAdjustment)baselineAdjust return nil; } ++ (NSArray *)baselineAdjustments { + NSMutableArray *adjustments = [[NSMutableArray alloc] init]; + for (UIBaselineAdjustment i = UIBaselineAdjustmentAlignBaselines; i <= UIBaselineAdjustmentNone; i++) { + NSString *adjustment = [self baselineAdjustmentDescription:i]; + if (adjustment) { + [adjustments addObject:adjustment]; + } + } + return adjustments; +} + + (NSString *)controlContentVerticalAlignmentDescription:(UIControlContentVerticalAlignment)contentVerticalAlignment { switch (contentVerticalAlignment) { case UIControlContentVerticalAlignmentCenter: @@ -152,6 +196,17 @@ + (NSString *)controlContentVerticalAlignmentDescription:(UIControlContentVertic return nil; } ++ (NSArray *)controlContentVerticalAlignments { + NSMutableArray *alignments = [[NSMutableArray alloc] init]; + for (UIControlContentVerticalAlignment i = UIControlContentVerticalAlignmentCenter; i <= UIControlContentVerticalAlignmentFill; i++) { + NSString *alignment = [self controlContentVerticalAlignmentDescription:i]; + if (alignment) { + [alignments addObject:alignment]; + } + } + return [alignments copy]; +} + + (NSString *)controlContentHorizontalAlignmentDescription:(UIControlContentHorizontalAlignment)contentHorizontalAlignment { switch (contentHorizontalAlignment) { case UIControlContentHorizontalAlignmentCenter: @@ -170,6 +225,21 @@ + (NSString *)controlContentHorizontalAlignmentDescription:(UIControlContentHori return nil; } ++ (NSArray *)controlContentHorizontalAlignments { + NSMutableArray *alignments = [[NSMutableArray alloc] init]; + UIControlContentHorizontalAlignment max = UIControlContentHorizontalAlignmentFill; + if (@available(iOS 11.0, *)) { + max = UIControlContentHorizontalAlignmentTrailing; + } + for (UIControlContentHorizontalAlignment i = UIControlContentHorizontalAlignmentCenter; i <= max; i++) { + NSString *alignment = [self controlContentHorizontalAlignmentDescription:i]; + if (alignment) { + [alignments addObject:alignment]; + } + } + return [alignments copy]; +} + + (NSString *)buttonTypeDescription:(UIButtonType)buttonType { switch (buttonType) { case UIButtonTypeCustom: @@ -228,6 +298,17 @@ + (NSString *)textBorderStyleDescription:(UITextBorderStyle)style { return nil; } ++ (NSArray *)textBorderStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (UITextBorderStyle i = UITextBorderStyleNone; i <= UITextBorderStyleRoundedRect; i++) { + NSString *style = [self textBorderStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + + (NSString *)textFieldViewModeDescription:(UITextFieldViewMode)mode { switch (mode) { case UITextFieldViewModeNever: @@ -242,7 +323,18 @@ + (NSString *)textFieldViewModeDescription:(UITextFieldViewMode)mode { return nil; } -+ (NSString *_Nullable)textAutocapitalizationTypeDescription:(UITextAutocapitalizationType)type { ++ (NSArray *)textFieldViewModes { + NSMutableArray *modes = [[NSMutableArray alloc] init]; + for (UITextFieldViewMode i = UITextFieldViewModeNever; i <= UITextFieldViewModeAlways; i++) { + NSString *mode = [self textFieldViewModeDescription:i]; + if (mode) { + [modes addObject:mode]; + } + } + return [modes copy]; +} + ++ (NSString *)textAutocapitalizationTypeDescription:(UITextAutocapitalizationType)type { switch (type) { case UITextAutocapitalizationTypeNone: return @"None"; @@ -256,19 +348,41 @@ + (NSString *_Nullable)textAutocapitalizationTypeDescription:(UITextAutocapitali return nil; } ++ (NSArray *)textAutocapitalizationTypes { + NSMutableArray *types = [[NSMutableArray alloc] init]; + for (UITextAutocapitalizationType i = UITextAutocapitalizationTypeNone; i <= UITextAutocapitalizationTypeAllCharacters; i++) { + NSString *type = [self textAutocapitalizationTypeDescription:i]; + if (type) { + [types addObject:type]; + } + } + return [types copy]; +} + + (NSString *)textAutocorrectionTypeDescription:(UITextAutocorrectionType)type { switch (type) { case UITextAutocorrectionTypeDefault: return @"Default"; - case UITextAutocorrectionTypeYes: - return @"YES"; case UITextAutocorrectionTypeNo: return @"NO"; + case UITextAutocorrectionTypeYes: + return @"YES"; } return nil; } -+ (NSString *_Nullable)keyboardTypeDescription:(UIKeyboardType)type { ++ (NSArray *)textAutocorrectionTypes { + NSMutableArray *types = [[NSMutableArray alloc] init]; + for (UITextAutocorrectionType i = 0; i <= UITextAutocorrectionTypeYes; i++) { + NSString *type = [self textAutocorrectionTypeDescription:i]; + if (type) { + [types addObject:type]; + } + } + return [types copy]; +} + ++ (NSString *)keyboardTypeDescription:(UIKeyboardType)type { switch (type) { case UIKeyboardTypeDefault: return @"Default"; @@ -298,6 +412,21 @@ + (NSString *_Nullable)keyboardTypeDescription:(UIKeyboardType)type { return nil; } ++ (NSArray *)keyboardTypes { + NSMutableArray *types = [[NSMutableArray alloc] init]; + UIKeyboardType max = UIKeyboardTypeWebSearch; + if (@available(iOS 10.0, *)) { + max = UIKeyboardTypeASCIICapableNumberPad; + } + for (UIKeyboardType i = UIKeyboardTypeDefault; i <= max; i++) { + NSString *type = [self keyboardTypeDescription:i]; + if (type) { + [types addObject:type]; + } + } + return [types copy]; +} + + (NSString *)keyboardAppearanceDescription:(UIKeyboardAppearance)appearance { switch (appearance) { case UIKeyboardAppearanceDefault: @@ -310,6 +439,17 @@ + (NSString *)keyboardAppearanceDescription:(UIKeyboardAppearance)appearance { return nil; } ++ (NSArray *)keyboardAppearances { + NSMutableArray *appearances = [[NSMutableArray alloc] init]; + for (UIKeyboardAppearance i = UIKeyboardAppearanceDefault; i <= UIKeyboardAppearanceLight; i++) { + NSString *appearance = [self keyboardAppearanceDescription:i]; + if (appearance) { + [appearances addObject:appearance]; + } + } + return [appearances copy]; +} + + (NSString *)returnKeyTypeDescription:(UIReturnKeyType)type { switch (type) { case UIReturnKeyDefault: @@ -340,7 +480,22 @@ + (NSString *)returnKeyTypeDescription:(UIReturnKeyType)type { return nil; } -+ (NSString *_Nullable)activityIndicatorViewStyleDescription:(UIActivityIndicatorViewStyle)style { ++ (NSArray *)returnKeyTypes { + NSMutableArray *types = [[NSMutableArray alloc] init]; + UIReturnKeyType max = UIReturnKeyEmergencyCall; + if (@available(iOS 9.0, *)) { + max = UIReturnKeyContinue; + } + for (UIReturnKeyType i = UIReturnKeyDefault; i <= max; i++) { + NSString *type = [self returnKeyTypeDescription:i]; + if (type) { + [types addObject:type]; + } + } + return [types copy]; +} + ++ (NSString *)activityIndicatorViewStyleDescription:(UIActivityIndicatorViewStyle)style { switch (style) { #ifdef __IPHONE_13_0 case UIActivityIndicatorViewStyleMedium: @@ -361,7 +516,27 @@ + (NSString *_Nullable)activityIndicatorViewStyleDescription:(UIActivityIndicato return nil; } -+ (NSString *_Nullable)progressViewStyleDescription:(UIProgressViewStyle)style { ++ (NSArray *)activityIndicatorViewStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSArray *actions = @[@(UIActivityIndicatorViewStyleWhiteLarge),@(UIActivityIndicatorViewStyleWhite),@(UIActivityIndicatorViewStyleGray)]; +#ifdef __IPHONE_13_0 + if (@available(iOS 13.0, *)) { + actions = @[@(UIActivityIndicatorViewStyleMedium),@(UIActivityIndicatorViewStyleLarge),@(UIActivityIndicatorViewStyleWhiteLarge),@(UIActivityIndicatorViewStyleWhite),@(UIActivityIndicatorViewStyleGray)]; + } +#endif +#pragma clang diagnostic pop + for (NSNumber *num in actions) { + NSString *style = [self activityIndicatorViewStyleDescription:[num integerValue]]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + ++ (NSString *)progressViewStyleDescription:(UIProgressViewStyle)style { switch (style) { case UIProgressViewStyleDefault: return @"Default"; @@ -371,7 +546,18 @@ + (NSString *_Nullable)progressViewStyleDescription:(UIProgressViewStyle)style { return nil; } -+ (NSString *_Nullable)scrollViewIndicatorStyleDescription:(UIScrollViewIndicatorStyle)style { ++ (NSArray *)progressViewStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (UIProgressViewStyle i = UIProgressViewStyleDefault; i <= UIProgressViewStyleBar; i++) { + NSString *style = [self progressViewStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + ++ (NSString *)scrollViewIndicatorStyleDescription:(UIScrollViewIndicatorStyle)style { switch (style) { case UIScrollViewIndicatorStyleDefault: return @"Default"; @@ -383,7 +569,18 @@ + (NSString *_Nullable)scrollViewIndicatorStyleDescription:(UIScrollViewIndicato return nil; } -+ (NSString *_Nullable)scrollViewKeyboardDismissModeDescription:(UIScrollViewKeyboardDismissMode)mode { ++ (NSArray *)scrollViewIndicatorStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (UIScrollViewIndicatorStyle i = UIScrollViewIndicatorStyleDefault; i <= UIScrollViewIndicatorStyleWhite; i++) { + NSString *style = [self scrollViewIndicatorStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + ++ (NSString *)scrollViewKeyboardDismissModeDescription:(UIScrollViewKeyboardDismissMode)mode { switch (mode) { case UIScrollViewKeyboardDismissModeNone: return @"Do not dismiss"; @@ -395,7 +592,18 @@ + (NSString *_Nullable)scrollViewKeyboardDismissModeDescription:(UIScrollViewKey return nil; } -+ (NSString *_Nullable)tableViewStyleDescription:(UITableViewStyle)style { ++ (NSArray *)scrollViewKeyboardDismissModes { + NSMutableArray *modes = [[NSMutableArray alloc] init]; + for (UIScrollViewKeyboardDismissMode i = UIScrollViewKeyboardDismissModeNone; i <= UIScrollViewKeyboardDismissModeInteractive; i++) { + NSString *mode = [self scrollViewKeyboardDismissModeDescription:i]; + if (mode) { + [modes addObject:mode]; + } + } + return [modes copy]; +} + ++ (NSString *)tableViewStyleDescription:(UITableViewStyle)style { switch (style) { case UITableViewStylePlain: return @"Plain"; @@ -409,7 +617,7 @@ + (NSString *_Nullable)tableViewStyleDescription:(UITableViewStyle)style { return nil; } -+ (NSString *_Nullable)tableViewCellSeparatorStyleDescription:(UITableViewCellSeparatorStyle)style { ++ (NSString *)tableViewCellSeparatorStyleDescription:(UITableViewCellSeparatorStyle)style { switch (style) { case UITableViewCellSeparatorStyleNone: return @"None"; @@ -424,7 +632,21 @@ + (NSString *_Nullable)tableViewCellSeparatorStyleDescription:(UITableViewCellSe return nil; } -+ (NSString *_Nullable)tableViewSeparatorInsetReferenceDescription:(UITableViewSeparatorInsetReference)reference { ++ (NSArray *)tableViewCellSeparatorStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + for (UITableViewCellSeparatorStyle i = UITableViewCellSeparatorStyleNone; i <= UITableViewCellSeparatorStyleSingleLineEtched; i++) { + NSString *style = [self tableViewCellSeparatorStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } +#pragma clang diagnostic pop + return [styles copy]; +} + ++ (NSString *)tableViewSeparatorInsetReferenceDescription:(UITableViewSeparatorInsetReference)reference { switch (reference) { case UITableViewSeparatorInsetFromCellEdges: return @"From Cell Edges"; @@ -434,7 +656,18 @@ + (NSString *_Nullable)tableViewSeparatorInsetReferenceDescription:(UITableViewS return nil; } -+ (NSString *_Nullable)tableViewCellSelectionStyleDescription:(UITableViewCellSelectionStyle)style { ++ (NSArray *)tableViewSeparatorInsetReferences { + NSMutableArray *references = [[NSMutableArray alloc] init]; + for (UITableViewSeparatorInsetReference i = UITableViewSeparatorInsetFromCellEdges; i <= UITableViewSeparatorInsetFromAutomaticInsets; i++) { + NSString *reference = [self tableViewSeparatorInsetReferenceDescription:i]; + if (reference) { + [references addObject:reference]; + } + } + return [references copy]; +} + ++ (NSString *)tableViewCellSelectionStyleDescription:(UITableViewCellSelectionStyle)style { switch (style) { case UITableViewCellSelectionStyleNone: return @"None"; @@ -448,7 +681,18 @@ + (NSString *_Nullable)tableViewCellSelectionStyleDescription:(UITableViewCellSe return nil; } -+ (NSString *_Nullable)tableViewCellAccessoryTypeDescription:(UITableViewCellAccessoryType)type { ++ (NSArray *)tableViewCellSelectionStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (UITableViewCellSelectionStyle i = UITableViewCellSelectionStyleNone; i <= UITableViewCellSelectionStyleDefault; i++) { + NSString *style = [self tableViewCellSelectionStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + ++ (NSString *)tableViewCellAccessoryTypeDescription:(UITableViewCellAccessoryType)type { switch (type) { case UITableViewCellAccessoryNone: return @"None"; @@ -464,7 +708,18 @@ + (NSString *_Nullable)tableViewCellAccessoryTypeDescription:(UITableViewCellAcc return nil; } -+ (NSString *_Nullable)datePickerModeDescription:(UIDatePickerMode)mode { ++ (NSArray *)tableViewCellAccessoryTypes { + NSMutableArray *types = [[NSMutableArray alloc] init]; + for (UITableViewCellAccessoryType i = UITableViewCellAccessoryNone; i <= UITableViewCellAccessoryDetailButton; i++) { + NSString *type = [self tableViewCellAccessoryTypeDescription:i]; + if (type) { + [types addObject:type]; + } + } + return [types copy]; +} + ++ (NSString *)datePickerModeDescription:(UIDatePickerMode)mode { switch (mode) { case UIDatePickerModeDate: return @"Date"; @@ -478,7 +733,18 @@ + (NSString *_Nullable)datePickerModeDescription:(UIDatePickerMode)mode { return nil; } -+ (NSString *_Nullable)barStyleDescription:(UIBarStyle)style { ++ (NSArray *)datePickerModes { + NSMutableArray *modes = [[NSMutableArray alloc] init]; + for (UIDatePickerMode i = UIDatePickerModeDate; i <= UIDatePickerModeCountDownTimer; i++) { + NSString *mode = [self datePickerModeDescription:i]; + if (mode) { + [modes addObject:mode]; + } + } + return [modes copy]; +} + ++ (NSString *)barStyleDescription:(UIBarStyle)style { switch (style) { case UIBarStyleDefault: return @"Default"; @@ -493,19 +759,44 @@ + (NSString *_Nullable)barStyleDescription:(UIBarStyle)style { return nil; } -+ (NSString *_Nullable)searchBarStyleDescription:(UISearchBarStyle)style { ++ (NSArray *)barStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + for (UIBarStyle i = UIBarStyleDefault; i <= UIBarStyleBlackTranslucent; i++) { + NSString *style = [self barStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } +#pragma clang diagnostic pop + return [styles copy]; +} + ++ (NSString *)searchBarStyleDescription:(UISearchBarStyle)style { switch (style) { case UISearchBarStyleDefault: return @"Default"; - case UISearchBarStyleMinimal: - return @"Minimal"; case UISearchBarStyleProminent: return @"Prominent"; + case UISearchBarStyleMinimal: + return @"Minimal"; } return nil; } -+ (NSString *_Nullable)tabBarItemPositioningDescription:(UITabBarItemPositioning)positioning { ++ (NSArray *)searchBarStyles { + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (UISearchBarStyle i = UISearchBarStyleDefault; i <= UISearchBarStyleMinimal; i++) { + NSString *style = [self searchBarStyleDescription:i]; + if (style) { + [styles addObject:style]; + } + } + return [styles copy]; +} + ++ (NSString *)tabBarItemPositioningDescription:(UITabBarItemPositioning)positioning { switch (positioning) { case UITabBarItemPositioningAutomatic: return @"Automatic"; @@ -517,4 +808,88 @@ + (NSString *_Nullable)tabBarItemPositioningDescription:(UITabBarItemPositioning return nil; } ++ (NSArray *)tabBarItemPositionings { + NSMutableArray *positionings = [[NSMutableArray alloc] init]; + for (UITabBarItemPositioning i = UITabBarItemPositioningAutomatic; i <= UITabBarItemPositioningCentered; i++) { + NSString *positioning = [self tabBarItemPositioningDescription:i]; + if (positioning) { + [positionings addObject:positioning]; + } + } + return [positionings copy]; +} + ++ (NSString *_Nullable)layoutAttributeDescription:(NSLayoutAttribute)attribute { + switch (attribute) { + case NSLayoutAttributeLeft: + return @"left"; + case NSLayoutAttributeRight: + return @"right"; + case NSLayoutAttributeTop: + return @"top"; + case NSLayoutAttributeBottom: + return @"bottom"; + case NSLayoutAttributeLeading: + return @"leading"; + case NSLayoutAttributeTrailing: + return @"trailing"; + case NSLayoutAttributeWidth: + return @"width"; + case NSLayoutAttributeHeight: + return @"height"; + case NSLayoutAttributeCenterX: + return @"centerX"; + case NSLayoutAttributeCenterY: + return @"centerY"; + case NSLayoutAttributeLastBaseline: + return @"lastBaseline"; + case NSLayoutAttributeFirstBaseline: + return @"firstBaseline"; + case NSLayoutAttributeLeftMargin: + return @"leftMargin"; + case NSLayoutAttributeRightMargin: + return @"rightMargin"; + case NSLayoutAttributeTopMargin: + return @"topMargin"; + case NSLayoutAttributeBottomMargin: + return @"bottomMargin"; + case NSLayoutAttributeLeadingMargin: + return @"leadingMargin"; + case NSLayoutAttributeTrailingMargin: + return @"trailingMargin"; + case NSLayoutAttributeCenterXWithinMargins: + return @"centerXMargin"; + case NSLayoutAttributeCenterYWithinMargins: + return @"centerYMargin"; + case NSLayoutAttributeNotAnAttribute: + return nil; + default: + return nil; + } +} + ++ (NSArray *)layoutAttributes { + NSMutableArray *attributes = [[NSMutableArray alloc] init]; + for (NSLayoutAttribute i = NSLayoutAttributeNotAnAttribute; i <= NSLayoutAttributeCenterYWithinMargins; i++) { + NSString *attribute = [self layoutAttributeDescription:i]; + if (attribute) { + [attributes addObject:attribute]; + } + } + return [attributes copy]; +} + ++ (NSString *_Nullable)layoutRelationDescription:(NSLayoutRelation)relation { + switch (relation) { + case NSLayoutRelationLessThanOrEqual: + return @"<="; + case NSLayoutRelationEqual: + return @"="; + case NSLayoutRelationGreaterThanOrEqual: + return @">="; + default: + return nil; + } +} + @end diff --git a/LLDebugTool/Core/Others/Tool/LLTool.h b/LLDebugTool/Core/Others/Tool/LLTool.h index 2b0e4487..95187a0f 100644 --- a/LLDebugTool/Core/Others/Tool/LLTool.h +++ b/LLDebugTool/Core/Others/Tool/LLTool.h @@ -58,6 +58,11 @@ NS_ASSUME_NONNULL_BEGIN */ + (UIWindow *)topWindow; +/** + Key window. + */ ++ (UIWindow *)keyWindow; + /** Internal log. diff --git a/LLDebugTool/Core/Others/Tool/LLTool.m b/LLDebugTool/Core/Others/Tool/LLTool.m index fc0da04f..04e88e98 100644 --- a/LLDebugTool/Core/Others/Tool/LLTool.m +++ b/LLDebugTool/Core/Others/Tool/LLTool.m @@ -87,6 +87,13 @@ + (UIWindow *)topWindow { return topWindow; } ++ (UIWindow *)keyWindow { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + return [UIApplication sharedApplication].keyWindow; +#pragma clang diagnostic pop +} + + (void)log:(NSString *)string { dispatch_async(dispatch_get_main_queue(), ^{ if ([LLConfig shared].isShowDebugToolLog) { diff --git a/LLDebugTool/DebugTool/LLConfig.m b/LLDebugTool/DebugTool/LLConfig.m index 5e15bddd..5a4913e7 100644 --- a/LLDebugTool/DebugTool/LLConfig.m +++ b/LLDebugTool/DebugTool/LLConfig.m @@ -181,7 +181,7 @@ - (void)initial { // Click action _clickAction = LLDebugToolActionFunction; - _doubleClickAction = LLDebugToolActionConvenientScreenshot; + _doubleClickAction = LLDebugToolActionHierarchy; // Set default window's style. _entryWindowStyle = LLConfigEntryWindowStyleBall; diff --git a/LLDebugTool/DebugTool/LLDebugTool.m b/LLDebugTool/DebugTool/LLDebugTool.m index d3073eb9..10e37f39 100644 --- a/LLDebugTool/DebugTool/LLDebugTool.m +++ b/LLDebugTool/DebugTool/LLDebugTool.m @@ -163,7 +163,7 @@ - (void)initial { // Set Default _isBetaVersion = NO; - _versionNumber = @"1.3.3"; + _versionNumber = @"1.3.4"; _version = _isBetaVersion ? [_versionNumber stringByAppendingString:@"(BETA)"] : _versionNumber; diff --git a/LLDebugToolDemo.xcodeproj/project.pbxproj b/LLDebugToolDemo.xcodeproj/project.pbxproj index ddef4eee..879fb67d 100644 --- a/LLDebugToolDemo.xcodeproj/project.pbxproj +++ b/LLDebugToolDemo.xcodeproj/project.pbxproj @@ -2610,7 +2610,7 @@ INFOPLIST_FILE = LLDebugToolDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.3.3; + MARKETING_VERSION = 1.3.4; PRODUCT_BUNDLE_IDENTIFIER = myCompany.HDB.LLDebugToolDemo; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2631,7 +2631,7 @@ INFOPLIST_FILE = LLDebugToolDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.3.3; + MARKETING_VERSION = 1.3.4; PRODUCT_BUNDLE_IDENTIFIER = myCompany.HDB.LLDebugToolDemo; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/LLDebugToolDemo.xcodeproj/xcshareddata/xcschemes/LLDebugToolDemo.xcscheme b/LLDebugToolDemo.xcodeproj/xcshareddata/xcschemes/LLDebugToolDemo.xcscheme index c67ee501..707bddcc 100644 --- a/LLDebugToolDemo.xcodeproj/xcshareddata/xcschemes/LLDebugToolDemo.xcscheme +++ b/LLDebugToolDemo.xcodeproj/xcshareddata/xcschemes/LLDebugToolDemo.xcscheme @@ -27,6 +27,15 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + @@ -49,17 +58,6 @@ - - - - - - - - [![Version](https://img.shields.io/badge/iOS-%3E%3D8.0-f07e48.svg)](https://img.shields.io/badge/iOS-%3E%3D8.0-f07e48.svg) -[![CocoaPods Compatible](https://img.shields.io/badge/Pod-v1.3.3-blue.svg)](https://img.shields.io/badge/Pod-v1.3.3-blue.svg) +[![CocoaPods Compatible](https://img.shields.io/badge/Pod-v1.3.4-blue.svg)](https://img.shields.io/badge/Pod-v1.3.4-blue.svg) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](https://img.shields.io/badge/Platform-iOS-lightgrey.svg)](https://img.shields.io/badge/Platform-iOS-lightgrey.svg) [![License](https://img.shields.io/badge/License-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE) @@ -45,15 +45,15 @@ LLDebugTool是一款针对开发者和测试者的调试工具,它可以帮助 -## 最近更新 (1.3.3) +## 最近更新 (1.3.4) -### 新增 `Html` 功能。 +### 更实用的 `Hierarchy` 功能 -你可以在你的app中随时调试通过 `WKWebView`,`UIWebView` 或者你自定义的`ViewController`来调试html页面。 +现在你可以用 `Hierarchy` 功能动态的修改属性值。在快捷界面里有常用的属性,在详情界面里有大部分的属性。 -#### 新增 +#### 更新 -* 现在 `LLURLProtocol` 可以正确的监听 `WKWebView`。 +* 更新 `Hierarchy Detail` 实现动态修改属性值的功能。 ## 我能用LLDebugTool做什么? @@ -71,7 +71,7 @@ LLDebugTool是一款针对开发者和测试者的调试工具,它可以帮助 - 截屏、标注并分享。 -- 更直观的查看视图结构。 +- 更直观的查看视图结构,并修改具体属性值。 - 更准确地确定App里的UI元素和颜色。 @@ -79,6 +79,8 @@ LLDebugTool是一款针对开发者和测试者的调试工具,它可以帮助 - 便捷的查看元素边框及位置。 +- 快速的Html容器入口。 + ## 添加 LLDebugTool 到你的项目中 ### CocoaPods @@ -87,17 +89,17 @@ LLDebugTool是一款针对开发者和测试者的调试工具,它可以帮助 ##### Objective - C -> 1. 添加 `pod 'LLDebugTool' , '~> 1.0.0'` 到你的Podfile里。 -> 2. 如果只想在Debug模式下使用,则添加`pod 'LLDebugTool' , '~> 1.0.0' ,:configurations => ['Debug']` 到你的Podfile里,详细的配置方式可以查看[Wiki/如何仅在Debug环境中使用](https://github.com/HDB-Li/LLDebugTool/wiki/如何仅在Debug环境中使用)。如果你想要指定某个版本,可以类似这样使用 `pod 'LLDebugTool' , '1.3.3' ,:configurations => ['Debug']`。 -> 3. 推荐的方式是采用多Target来处理,只在Debug Target中添加`pod 'LLDebugTool' , '~> 1.0.0'`,这样做的好处既不污染Product环境的代码,又可以在Archive Debug环境的App时,将`LLDebugTool`集成进去(如果采用`:configurations => ['Debug']`的方式,只能通过XCode运行,不可以Archive成App)。 +> 1. 添加 `pod 'LLDebugTool' , '~> 1.0'` 到你的Podfile里。 +> 2. 如果只想在Debug模式下使用,则添加`pod 'LLDebugTool' , '~> 1.0' ,:configurations => ['Debug']` 到你的Podfile里,详细的配置方式可以查看[Wiki/如何仅在Debug环境中使用](https://github.com/HDB-Li/LLDebugTool/wiki/如何仅在Debug环境中使用)。如果你想要指定某个版本,可以类似这样使用 `pod 'LLDebugTool' , '1.3.4' ,:configurations => ['Debug']`。 +> 3. 推荐的方式是采用多Target来处理,只在Debug Target中添加`pod 'LLDebugTool' , '~> 1.0'`,这样做的好处既不污染Product环境的代码,又可以在Archive Debug环境的App时,将`LLDebugTool`集成进去(如果采用`:configurations => ['Debug']`的方式,只能通过XCode运行,不可以Archive成App)。 > 4. 终端输入`pod install`来进行集成。搜索不到`LLDebugTool`或者搜不到最新版本时,可先运行`pod repo update`,再执行`pod install`。 > 5. 在你需要使用LLDebugTool的文件里添加`#import "LLDebug.h"`,或者直接在pch文件中添加`#import "LLDebug.h"`。 ##### Swift -> 1. 添加 `pod 'LLDebugToolSwift' , '~> 1.0.0'` 到你的Podfile里。 -> 2. 如果只想在Debug模式下使用,则添加`pod 'LLDebugToolSwift' , '~> 1.0.0' ,:configurations => ['Debug']` 到你的Podfile里,详细的配置方式可以查看[Wiki/如何仅在Debug环境中使用](https://github.com/HDB-Li/LLDebugTool/wiki/如何仅在Debug环境中使用)。如果你想要指定某个版本,可以类似这样使用 `pod 'LLDebugToolSwift' , '1.3.3' ,:configurations => ['Debug']`。 -> 3. 推荐的方式是采用多Target来处理,只在Debug Target中添加`pod 'LLDebugToolSwift' , '~> 1.0.0'`,这样做的好处既不污染Product环境的代码,又可以在Archive Debug环境的App时,将`LLDebugToolSwift`集成进去(如果采用`:configurations => ['Debug']`的方式,只能通过XCode运行,不可以Archive成App)。 +> 1. 添加 `pod 'LLDebugToolSwift' , '~> 1.0'` 到你的Podfile里。 +> 2. 如果只想在Debug模式下使用,则添加`pod 'LLDebugToolSwift' , '~> 1.0' ,:configurations => ['Debug']` 到你的Podfile里,详细的配置方式可以查看[Wiki/如何仅在Debug环境中使用](https://github.com/HDB-Li/LLDebugTool/wiki/如何仅在Debug环境中使用)。如果你想要指定某个版本,可以类似这样使用 `pod 'LLDebugToolSwift' , '1.3.4' ,:configurations => ['Debug']`。 +> 3. 推荐的方式是采用多Target来处理,只在Debug Target中添加`pod 'LLDebugToolSwift' , '~> 1.0'`,这样做的好处既不污染Product环境的代码,又可以在Archive Debug环境的App时,将`LLDebugToolSwift`集成进去(如果采用`:configurations => ['Debug']`的方式,只能通过XCode运行,不可以Archive成App)。 > 4. 必须在Podfile中添加 **`use_frameworks!`** 。 > 5. 终端输入`pod install`来进行集成。搜索不到`LLDebugToolSwift`或者搜不到最新版本时,可先运行`pod repo update`,再执行`pod install`。 > 6. 在你需要使用LLDebugTool的文件里添加`import LLDebugToolSwift`。 @@ -324,7 +326,7 @@ LLDebugTool提供了一个截屏功能,并且可以进行简单的绘画和标 ### 视图结构 -LLDebugTool提供了一个视图结构工具,用于在非Debug模式下查看元素的属性和信息。 +LLDebugTool提供了一个视图结构工具,用于在非Debug模式下查看或者修改元素的属性和信息。 ### 放大镜 diff --git a/README.md b/README.md index 11b005e1..e4e25b78 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

[![Version](https://img.shields.io/badge/iOS-%3E%3D8.0-f07e48.svg)](https://img.shields.io/badge/iOS-%3E%3D8.0-f07e48.svg) -[![CocoaPods Compatible](https://img.shields.io/badge/pod-v1.3.3-blue.svg)](https://img.shields.io/badge/pod-v1.3.3-blue.svg) +[![CocoaPods Compatible](https://img.shields.io/badge/pod-v1.3.4-blue.svg)](https://img.shields.io/badge/pod-v1.3.4-blue.svg) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](https://img.shields.io/badge/Platform-iOS-lightgrey.svg)](https://img.shields.io/badge/Platform-iOS-lightgrey.svg) [![License](https://img.shields.io/badge/License-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE) @@ -45,15 +45,15 @@ Choose LLDebugTool for your next project, or migrate over your existing projects -## What's new in 1.3.3 +## What's new in 1.3.4 -### Add `Html` function. +### More practical `Hierarchy` function -You can debug HTML pages through `WKWebView`, `UIWebView` or your customized `ViewController` in your app at any time. +Now you can use the `Hierarchy` function to dynamically modify attribute values. There are common attributes in the shortcut interface and most attributes in the details interface. It's a very interesting and useful function. -#### Add +#### Update -* Now `LLURLProtocol` can correctly observe `WKWebView`. +* Update `Hierarchy Detail` to dynamic modify properties. ## What can you do with LLDebugTool? @@ -71,7 +71,7 @@ You can debug HTML pages through `WKWebView`, `UIWebView` or your customized `Vi - take screenshots, tag and share. -- more intuitive view of view structure. +- more intuitive view of view structure and dynamic modify properties. - determine UI elements and colors in your App more accurately. @@ -79,6 +79,8 @@ You can debug HTML pages through `WKWebView`, `UIWebView` or your customized `Vi - easy access to element borders and frames. +- quick entry for html. + ## Adding LLDebugTool to your project ### CocoaPods @@ -87,17 +89,17 @@ You can debug HTML pages through `WKWebView`, `UIWebView` or your customized `Vi ##### Objective - C -> 1. Add a pod entry for LLDebugTool to your Podfile `pod 'LLDebugTool' , '~> 1.0.0'`. -> 2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugTool to your Podfile `pod 'LLDebugTool' , '~> 1.0.0' ,:configurations => ['Debug']`, Details also see [Wiki/Use in Debug environment](https://github.com/HDB-Li/LLDebugTool/wiki/Use-in-Debug-environment). If you want to specify the version, use as `pod 'LLDebugTool' , '1.3.3' ,:configurations => ['Debug']`. -> 3. The recommended approach is to use multiple targets and only add `pod 'LLDebugTool', '~> 1.0.0'` to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if `:configurations => ['Debug']`, it can only run through XCode. It is not possible to Archive as an App). +> 1. Add a pod entry for LLDebugTool to your Podfile `pod 'LLDebugTool' , '~> 1.0'`. +> 2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugTool to your Podfile `pod 'LLDebugTool' , '~> 1.0' ,:configurations => ['Debug']`, Details also see [Wiki/Use in Debug environment](https://github.com/HDB-Li/LLDebugTool/wiki/Use-in-Debug-environment). If you want to specify the version, use as `pod 'LLDebugTool' , '1.3.4' ,:configurations => ['Debug']`. +> 3. The recommended approach is to use multiple targets and only add `pod 'LLDebugTool', '~> 1.0'` to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if `:configurations => ['Debug']`, it can only run through XCode. It is not possible to Archive as an App). > 4. Install the pod(s) by running `pod install`. If you can't search `LLDebugTool` or you can't find the newest release version, running `pod repo update` before `pod install`. > 5. Include LLDebugTool wherever you need it with `#import "LLDebug.h"` or you can write `#import "LLDebug.h"` in your .pch in your .pch file. ##### Swift -> 1. Add a pod entry for LLDebugToolSwift to your Podfile `pod 'LLDebugToolSwift' , '~> 1.0.0'`. -> 2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugToolSwift to your Podfile `pod 'LLDebugToolSwift' , '~> 1.0.0' ,:configurations => ['Debug']`, Details also see [Wiki/Use in Debug environment](https://github.com/HDB-Li/LLDebugTool/wiki/Use-in-Debug-environment). If you want to specify the version, use as `pod 'LLDebugToolSwift' , '1.3.3' ,:configurations => ['Debug']`. -> 3. The recommended approach is to use multiple targets and only add `pod 'LLDebugToolSwift', '~> 1.0.0'` to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if `:configurations => ['Debug']`, it can only run through XCode. It is not possible to Archive as an App). +> 1. Add a pod entry for LLDebugToolSwift to your Podfile `pod 'LLDebugToolSwift' , '~> 1.0'`. +> 2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugToolSwift to your Podfile `pod 'LLDebugToolSwift' , '~> 1.0' ,:configurations => ['Debug']`, Details also see [Wiki/Use in Debug environment](https://github.com/HDB-Li/LLDebugTool/wiki/Use-in-Debug-environment). If you want to specify the version, use as `pod 'LLDebugToolSwift' , '1.3.4' ,:configurations => ['Debug']`. +> 3. The recommended approach is to use multiple targets and only add `pod 'LLDebugToolSwift', '~> 1.0'` to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if `:configurations => ['Debug']`, it can only run through XCode. It is not possible to Archive as an App). > 4. Must be added in the Podfile **`use_frameworks!`**. > 5. Install the pod(s) by running `pod install`. If you can't search `LLDebugToolSwift` or you can't find the newest release version, running `pod repo update` before `pod install`. > 6. Include LLDebugTool wherever you need it with `import "LLDebugToolSwift`. @@ -324,7 +326,7 @@ LLDebugTool provides a screenshot and allows for simple painting and marking tha ### Hierarchy -LLDebugTool provides a view structure tool for viewing elements' properties and information in non-debug mode. +LLDebugTool provides a view structure tool for viewing or modify elements' properties and information in non-debug mode. ### Magnifier