diff --git a/Demo/Pods/Pods.xcodeproj/project.pbxproj b/Demo/Pods/Pods.xcodeproj/project.pbxproj index 60b5a96..63b60f2 100644 --- a/Demo/Pods/Pods.xcodeproj/project.pbxproj +++ b/Demo/Pods/Pods.xcodeproj/project.pbxproj @@ -11,6 +11,14 @@ 017D43B065C9D4444CF7B72F9746E6C2 /* XYDebugView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0491CDAF6E0F629383F698D2C3B90F /* XYDebugView-dummy.m */; }; 4EEAAEDA15C92F89A2058937381D1AC7 /* Pods-XYDebugView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2805323F23F24E0BDAB9E0432F5B9547 /* Pods-XYDebugView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5681F2EB82C5AE4F2F531ABE76C4FB02 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */; }; + 65758CD51ED6B75800A7738D /* XYDebugView.h in Headers */ = {isa = PBXBuildFile; fileRef = 65758CC51ED6B16700A7738D /* XYDebugView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 65758CD61ED6B75F00A7738D /* XYDebugView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65758CC61ED6B16700A7738D /* XYDebugView.m */; }; + 65758CD71ED6B76B00A7738D /* UIView+XYDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 65758CC91ED6B1EA00A7738D /* UIView+XYDebug.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 65758CD81ED6B76B00A7738D /* UIView+XYDebug.m in Sources */ = {isa = PBXBuildFile; fileRef = 65758CCA1ED6B1EA00A7738D /* UIView+XYDebug.m */; }; + 65758CD91ED6B76B00A7738D /* UIColor+XYRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 65758CCD1ED6B36500A7738D /* UIColor+XYRandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 65758CDA1ED6B76B00A7738D /* UIColor+XYRandom.m in Sources */ = {isa = PBXBuildFile; fileRef = 65758CCE1ED6B36500A7738D /* UIColor+XYRandom.m */; }; + 65758CDB1ED6B76B00A7738D /* XYDebugWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 65758CD11ED6B49D00A7738D /* XYDebugWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 65758CDC1ED6B76B00A7738D /* XYDebugWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 65758CD21ED6B49D00A7738D /* XYDebugWindow.m */; }; CB9B5B0878030C8F3B0C8D7AB6F51798 /* XYDebugView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D7CEEED1FC6CF357BDC3D5DFB6516007 /* XYDebugView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; D7EB363CCCE23344A0B9A88158CBDD14 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */; }; D90865DD8E1D3C2EE659E24B8371FEBA /* XYDebugViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FA68E19D380091EDD61A5303FB91BD3 /* XYDebugViewManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -34,19 +42,27 @@ 1015DB7E842A3A4E0B4117E346C04713 /* XYDebugView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XYDebugView-prefix.pch"; sourceTree = ""; }; 228DBEB9B6B43935E078AB3A2B06B779 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2805323F23F24E0BDAB9E0432F5B9547 /* Pods-XYDebugView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-XYDebugView-umbrella.h"; sourceTree = ""; }; - 4C5D0AD0B87ACE7DCD1F302162A0EABE /* XYDebugView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = XYDebugView.framework; path = XYDebugView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C5D0AD0B87ACE7DCD1F302162A0EABE /* XYDebugView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XYDebugView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4DAD1C7035182AA3EC2731048C0AA9D9 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 65758CC51ED6B16700A7738D /* XYDebugView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XYDebugView.h; sourceTree = ""; }; + 65758CC61ED6B16700A7738D /* XYDebugView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XYDebugView.m; sourceTree = ""; }; + 65758CC91ED6B1EA00A7738D /* UIView+XYDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+XYDebug.h"; sourceTree = ""; }; + 65758CCA1ED6B1EA00A7738D /* UIView+XYDebug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+XYDebug.m"; sourceTree = ""; }; + 65758CCD1ED6B36500A7738D /* UIColor+XYRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+XYRandom.h"; sourceTree = ""; }; + 65758CCE1ED6B36500A7738D /* UIColor+XYRandom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+XYRandom.m"; sourceTree = ""; }; + 65758CD11ED6B49D00A7738D /* XYDebugWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XYDebugWindow.h; sourceTree = ""; }; + 65758CD21ED6B49D00A7738D /* XYDebugWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XYDebugWindow.m; sourceTree = ""; }; 673B533F55EDC63E67F58CE05E9F28FA /* Pods-XYDebugView-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-XYDebugView-acknowledgements.markdown"; sourceTree = ""; }; 6FA68E19D380091EDD61A5303FB91BD3 /* XYDebugViewManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = XYDebugViewManager.h; path = XYDebugView/XYDebugViewManager.h; sourceTree = ""; }; - 700530F91F2C07FD4B342C8ACF68EA16 /* XYDebugView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = XYDebugView.modulemap; sourceTree = ""; }; + 700530F91F2C07FD4B342C8ACF68EA16 /* XYDebugView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = XYDebugView.modulemap; sourceTree = ""; }; 8048B0E9D35DE1CDB2B3576FACCB630F /* Pods-XYDebugView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-XYDebugView.debug.xcconfig"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - B15842E57C44AA39F8ECC832AF81E271 /* Pods-XYDebugView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-XYDebugView.modulemap"; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + B15842E57C44AA39F8ECC832AF81E271 /* Pods-XYDebugView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-XYDebugView.modulemap"; sourceTree = ""; }; B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; C72A222FF268CFE1DE1ACCCEBDD44F82 /* Pods-XYDebugView-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-XYDebugView-resources.sh"; sourceTree = ""; }; CE4495B08551BEC3D8C98ADAAF7BD7C6 /* Pods-XYDebugView-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-XYDebugView-acknowledgements.plist"; sourceTree = ""; }; D7CEEED1FC6CF357BDC3D5DFB6516007 /* XYDebugView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XYDebugView-umbrella.h"; sourceTree = ""; }; - D7DE256D1960668E0DB38B1887692C46 /* Pods_XYDebugView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_XYDebugView.framework; path = "Pods-XYDebugView.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + D7DE256D1960668E0DB38B1887692C46 /* Pods_XYDebugView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_XYDebugView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; DD0491CDAF6E0F629383F698D2C3B90F /* XYDebugView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "XYDebugView-dummy.m"; sourceTree = ""; }; E92E5754B278373A00C1F9DCCCC09F17 /* Pods-XYDebugView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-XYDebugView.release.xcconfig"; sourceTree = ""; }; @@ -149,9 +165,16 @@ children = ( 6FA68E19D380091EDD61A5303FB91BD3 /* XYDebugViewManager.h */, FD292D03A3747EB1F9BA923B2DE72086 /* XYDebugViewManager.m */, + 65758CC51ED6B16700A7738D /* XYDebugView.h */, + 65758CC61ED6B16700A7738D /* XYDebugView.m */, + 65758CC91ED6B1EA00A7738D /* UIView+XYDebug.h */, + 65758CCA1ED6B1EA00A7738D /* UIView+XYDebug.m */, + 65758CCD1ED6B36500A7738D /* UIColor+XYRandom.h */, + 65758CCE1ED6B36500A7738D /* UIColor+XYRandom.m */, + 65758CD11ED6B49D00A7738D /* XYDebugWindow.h */, + 65758CD21ED6B49D00A7738D /* XYDebugWindow.m */, 4DCCEDC5FD39673DADAA7023200C29D3 /* Support Files */, ); - name = XYDebugView; path = XYDebugView; sourceTree = ""; }; @@ -186,8 +209,12 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 65758CD91ED6B76B00A7738D /* UIColor+XYRandom.h in Headers */, CB9B5B0878030C8F3B0C8D7AB6F51798 /* XYDebugView-umbrella.h in Headers */, D90865DD8E1D3C2EE659E24B8371FEBA /* XYDebugViewManager.h in Headers */, + 65758CDB1ED6B76B00A7738D /* XYDebugWindow.h in Headers */, + 65758CD71ED6B76B00A7738D /* UIView+XYDebug.h in Headers */, + 65758CD51ED6B75800A7738D /* XYDebugView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -261,8 +288,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 65758CDC1ED6B76B00A7738D /* XYDebugWindow.m in Sources */, + 65758CDA1ED6B76B00A7738D /* UIColor+XYRandom.m in Sources */, 017D43B065C9D4444CF7B72F9746E6C2 /* XYDebugView-dummy.m in Sources */, 00CADD8508F38C4F931BFD2CF3BB8C7E /* XYDebugViewManager.m in Sources */, + 65758CD61ED6B75F00A7738D /* XYDebugView.m in Sources */, + 65758CD81ED6B76B00A7738D /* UIView+XYDebug.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Demo/Pods/XYDebugView/UIColor+XYRandom.h b/Demo/Pods/XYDebugView/UIColor+XYRandom.h new file mode 100644 index 0000000..14c00bd --- /dev/null +++ b/Demo/Pods/XYDebugView/UIColor+XYRandom.h @@ -0,0 +1,19 @@ +// +// UIColor+XYDebug.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import + +@interface UIColor (XYRandom) + ++ (UIColor *)randomLightColorWithAlpha:(CGFloat)alpha; + ++ (UIColor *)randomDrakColorWithAlpha:(CGFloat)alpha; + +@end + + diff --git a/Demo/Pods/XYDebugView/UIColor+XYRandom.m b/Demo/Pods/XYDebugView/UIColor+XYRandom.m new file mode 100644 index 0000000..c00f0f4 --- /dev/null +++ b/Demo/Pods/XYDebugView/UIColor+XYRandom.m @@ -0,0 +1,30 @@ +// +// UIColor+XYDebug.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "UIColor+XYRandom.h" + +@implementation UIColor (XYRandom) + ++ (UIColor *)randomLightColorWithAlpha:(CGFloat)alpha +{ + + return [UIColor colorWithRed:(arc4random()%100+155)/255.0 + green:(arc4random()%100+155)/255.0 + blue:(arc4random()%100+155)/255.0 + alpha:alpha]; +} + ++ (UIColor *)randomDrakColorWithAlpha:(CGFloat)alpha +{ + + return [UIColor colorWithRed:(arc4random()%150)/255.0 + green:(arc4random()%150)/255.0 + blue:(arc4random()%150)/255.0 + alpha:alpha]; +} +@end diff --git a/Demo/Pods/XYDebugView/UIView+XYDebug.h b/Demo/Pods/XYDebugView/UIView+XYDebug.h new file mode 100644 index 0000000..cc3df65 --- /dev/null +++ b/Demo/Pods/XYDebugView/UIView+XYDebug.h @@ -0,0 +1,19 @@ +// +// UIView+XYDebug.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugView.h" + +@interface UIView (XYDebug) + +@property (nonatomic, strong) UIColor *debugStoreOrginalColor; +@property (nonatomic, assign) BOOL hasStoreDebugColor; +@property (nonatomic, strong, readonly) CALayer *debugColorSublayer; +@property (nonatomic, strong, readonly) XYDebugCloneView *cloneView; +@property (nonatomic, copy, readonly) NSArray *debuRecurrenceAllSubviews; + +@end diff --git a/Demo/Pods/XYDebugView/UIView+XYDebug.m b/Demo/Pods/XYDebugView/UIView+XYDebug.m new file mode 100644 index 0000000..1365cd6 --- /dev/null +++ b/Demo/Pods/XYDebugView/UIView+XYDebug.m @@ -0,0 +1,86 @@ +// +// UIView+XYDebug.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "UIView+XYDebug.h" +#import + +const static char * DebugStoreUIViewBackColor = "DebugStoreUIViewBackColor"; +const static char * DebugHasStoreUIViewBackColor = "DebugHasStoreUIViewBackColor"; +const static char * DebugCloneView = "DebugCloneView"; +const static char * DebugColorSublayer = "DebugColorSublayer"; + +@implementation UIView (XYDebug) + +- (void)setDebugStoreOrginalColor:(UIColor *)debugStoreOrginalColor +{ + if ([debugStoreOrginalColor isKindOfClass:[UIColor class]] && debugStoreOrginalColor) { + objc_setAssociatedObject(self, DebugStoreUIViewBackColor, debugStoreOrginalColor, OBJC_ASSOCIATION_RETAIN); + } +} + +- (UIColor *)debugStoreOrginalColor +{ + id obj = objc_getAssociatedObject(self, DebugStoreUIViewBackColor); + if ([obj isKindOfClass:[UIColor class]]) { + return (UIColor *)obj; + } + return nil; +} + +- (CALayer *)debugColorSublayer +{ + CALayer *obj = objc_getAssociatedObject(self, DebugColorSublayer); + if ([obj isKindOfClass:[CALayer class]] && obj) { + obj.frame = self.bounds; + return obj; + } + obj = [[CALayer alloc] init]; + obj.borderColor = [[UIColor redColor] colorWithAlphaComponent:0.3].CGColor; + obj.borderWidth = 1/[UIScreen mainScreen].scale; + objc_setAssociatedObject(self, DebugColorSublayer, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return [self debugColorSublayer]; +} + +- (XYDebugCloneView *)cloneView +{ + XYDebugCloneView *obj = objc_getAssociatedObject(self, DebugCloneView); + if ([obj isKindOfClass:[XYDebugCloneView class]] && obj) { + return obj; + } + obj = [XYDebugCloneView cloneWith:self]; + obj.debugColorSublayer.frame = obj.bounds; + [obj.layer addSublayer:obj.debugColorSublayer]; + objc_setAssociatedObject(self, DebugCloneView, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return [self cloneView]; +} + +- (void)setHasStoreDebugColor:(BOOL)hasStoreDebugColor +{ + objc_setAssociatedObject(self, DebugHasStoreUIViewBackColor, @(hasStoreDebugColor), OBJC_ASSOCIATION_ASSIGN); +} + +- (BOOL)hasStoreDebugColor +{ + id obj = objc_getAssociatedObject(self, DebugHasStoreUIViewBackColor); + return [obj boolValue]; +} + +- (NSArray *)debuRecurrenceAllSubviews +{ + NSMutableArray *all = @[].mutableCopy; + void (^getSubViewsBlock)(UIView *current) = ^(UIView *current){ + [all addObject:current]; + for (UIView *sub in current.subviews) { + [all addObjectsFromArray:[sub debuRecurrenceAllSubviews]]; + } + }; + getSubViewsBlock(self); + return [NSArray arrayWithArray:all]; +} + +@end diff --git a/Demo/Pods/XYDebugView/XYDebugView.h b/Demo/Pods/XYDebugView/XYDebugView.h new file mode 100644 index 0000000..99b0518 --- /dev/null +++ b/Demo/Pods/XYDebugView/XYDebugView.h @@ -0,0 +1,24 @@ +// +// XYDebugCloneView.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import + +@interface XYDebugCloneView : UIView + ++ (XYDebugCloneView *)cloneWith:(UIView *)view; + +@end + + +@interface DebugSlider : UIView + +@property void (^touchMoveBlock)(float percent); + +@property void (^touchEndBlock)(); + +@end diff --git a/Demo/Pods/XYDebugView/XYDebugView.m b/Demo/Pods/XYDebugView/XYDebugView.m new file mode 100644 index 0000000..7ccae5b --- /dev/null +++ b/Demo/Pods/XYDebugView/XYDebugView.m @@ -0,0 +1,88 @@ +// +// XYDebugCloneView.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugView.h" +#import "UIColor+XYRandom.h" + +@interface XYDebugCloneView () + +@property(nonatomic, weak) UIView *srcView; + +@end + +@implementation XYDebugCloneView + ++ (XYDebugCloneView *)cloneWith:(UIView *)view +{ + return [[XYDebugCloneView alloc] initWithCopyView:view]; +} + +- (instancetype)initWithCopyView:(UIView *)srcView +{ + self = [super initWithFrame:srcView.frame]; + if (self) { + self.srcView = srcView; + self.backgroundColor = [UIColor randomLightColorWithAlpha:1]; + } + return self; +} + +- (void)drawRect:(CGRect)rect +{ + NSMutableArray *mArr = self.srcView.layer.sublayers.mutableCopy; + for (UIView *subview in self.srcView.subviews) { + if ([mArr containsObject:subview.layer]) { + [mArr removeObject:subview.layer]; + } + } + CALayer *newLayer = [CALayer layer]; + newLayer.contents = self.srcView.layer.contents; + newLayer.frame = self.srcView.layer.frame; + + for (CALayer *sublayer in mArr) { + CALayer *newSub = [[CALayer alloc] initWithLayer:sublayer]; + newSub.frame = sublayer.frame; + [newLayer addSublayer:newSub]; + } + [newLayer renderInContext:UIGraphicsGetCurrentContext()]; +} +@end + + +@implementation DebugSlider +{ + CALayer *_colorLayer; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + _colorLayer = [CALayer layer]; + _colorLayer.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor; + [self.layer addSublayer:_colorLayer]; + } + return self; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; + _colorLayer.frame = CGRectMake(0, 0, self.bounds.size.width, point.y); + float percent = point.y / self.frame.size.height; + percent = percent<0 ? percent : (percent>1 ? 1:percent); + !_touchMoveBlock ?: _touchMoveBlock(percent); +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + _colorLayer.frame = CGRectZero; + !_touchEndBlock ?: _touchEndBlock(); +} + +@end diff --git a/Demo/Pods/XYDebugView/XYDebugView/XYDebugViewManager.m b/Demo/Pods/XYDebugView/XYDebugView/XYDebugViewManager.m index 9f181db..ad3eb7d 100644 --- a/Demo/Pods/XYDebugView/XYDebugView/XYDebugViewManager.m +++ b/Demo/Pods/XYDebugView/XYDebugView/XYDebugViewManager.m @@ -7,343 +7,9 @@ // #import "XYDebugViewManager.h" -#import - -#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width -#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height - -#pragma mark - UIColor random - -@interface UIColor (Random) -+ (UIColor *)randomColorWithAlpha:(CGFloat)alpha; -@end - -@implementation UIColor (Random) -+ (UIColor *)randomColorWithAlpha:(CGFloat)alpha -{ - - return [UIColor colorWithRed:(arc4random()%155+100)/255.0 - green:(arc4random()%155+100)/255.0 - blue:(arc4random()%155+100)/255.0 - alpha:alpha]; -} -@end - -#pragma mark - CloneView -@interface CloneView : UIView -@property(nonatomic, weak) UIView *srcView; -+ (CloneView *)cloneWith:(UIView *)view; -@end - -@implementation CloneView -+ (CloneView *)cloneWith:(UIView *)view{ - return [[CloneView alloc] initWithCopyView:view]; -} -- (instancetype)initWithCopyView:(UIView *)srcView{ - self = [super initWithFrame:srcView.frame]; - if (self) { - self.srcView = srcView; - self.backgroundColor = [UIColor randomColorWithAlpha:0.6]; - } - return self; -} -- (void)drawRect:(CGRect)rect{ - NSMutableArray *mArr = self.srcView.layer.sublayers.mutableCopy; - for (UIView *subview in self.srcView.subviews) { - if ([mArr containsObject:subview.layer]) { - [mArr removeObject:subview.layer]; - } - } - CALayer *newLayer = [CALayer layer]; - newLayer.contents = self.srcView.layer.contents; - newLayer.frame = self.srcView.layer.frame; - - for (CALayer *sublayer in mArr) { - CALayer *newSub = [[CALayer alloc] initWithLayer:sublayer]; - newSub.frame = sublayer.frame; - [newLayer addSublayer:newSub]; - } - [newLayer renderInContext:UIGraphicsGetCurrentContext()]; -} -@end - -#pragma mark - UIView runtime 添加属性 - -const static char * DebugStoreUIViewBackColor = "DebugStoreUIViewBackColor"; -const static char * DebugHasStoreUIViewBackColor = "DebugHasStoreUIViewBackColor"; -const static char * DebugCloneView = "DebugCloneView"; -const static char * DebugCloneLayer = "DebugCloneLayer"; -const static char * DebugColorSublayer = "DebugColorSublayer"; - - -@interface UIView (DebugStoreUIViewBackColor) - -@property (nonatomic, strong) UIColor *debugStoreOrginalColor; -@property (nonatomic, assign) BOOL hasStoreDebugColor; -@property (nonatomic, strong, readonly) CALayer *debugColorSublayer; -@property (nonatomic, strong, readonly) CloneView *cloneView; -@property (nonatomic, strong, readonly) CALayer *cloneLayer; -@property (nonatomic, copy, readonly) NSArray *debuRecurrenceAllSubviews; - -@end - -@implementation UIView (DebugStoreUIViewBackColor) - -- (void)setDebugStoreOrginalColor:(UIColor *)debugStoreOrginalColor -{ - if ([debugStoreOrginalColor isKindOfClass:[UIColor class]] && debugStoreOrginalColor) { - objc_setAssociatedObject(self, DebugStoreUIViewBackColor, debugStoreOrginalColor, OBJC_ASSOCIATION_RETAIN); - } -} - -- (UIColor *)debugStoreOrginalColor -{ - id obj = objc_getAssociatedObject(self, DebugStoreUIViewBackColor); - if ([obj isKindOfClass:[UIColor class]]) { - return (UIColor *)obj; - } - return nil; -} - -- (CALayer *)debugColorSublayer -{ - CALayer *obj = objc_getAssociatedObject(self, DebugColorSublayer); - if ([obj isKindOfClass:[CALayer class]] && obj) { - obj.frame = self.bounds; - return obj; - } - obj = [[CALayer alloc] init]; - obj.borderColor = [[UIColor redColor] colorWithAlphaComponent:0.2].CGColor; - obj.borderWidth = 1/[UIScreen mainScreen].scale; - objc_setAssociatedObject(self, DebugColorSublayer, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return [self debugColorSublayer]; -} - -- (CloneView *)cloneView -{ - CloneView *obj = objc_getAssociatedObject(self, DebugCloneView); - if ([obj isKindOfClass:[CloneView class]] && obj) { - return obj; - } - obj = [CloneView cloneWith:self]; - objc_setAssociatedObject(self, DebugCloneView, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return [self cloneView]; -} - -- (CALayer *)cloneLayer -{ - CALayer *obj = objc_getAssociatedObject(self, DebugCloneLayer); - if ([obj isKindOfClass:[CALayer class]] && obj) { - return obj; - } - obj = [CALayer layer]; - obj.contents = self.layer.contents; - objc_setAssociatedObject(self, DebugCloneLayer, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return [self cloneLayer]; -} - -- (void)setHasStoreDebugColor:(BOOL)hasStoreDebugColor -{ - objc_setAssociatedObject(self, DebugHasStoreUIViewBackColor, @(hasStoreDebugColor), OBJC_ASSOCIATION_ASSIGN); -} - -- (BOOL)hasStoreDebugColor -{ - id obj = objc_getAssociatedObject(self, DebugHasStoreUIViewBackColor); - return [obj boolValue]; -} - -- (NSArray *)debuRecurrenceAllSubviews -{ - NSMutableArray *all = @[].mutableCopy; - void (^getSubViewsBlock)(UIView *current) = ^(UIView *current){ - [all addObject:current]; - for (UIView *sub in current.subviews) { - [all addObjectsFromArray:[sub debuRecurrenceAllSubviews]]; - } - }; - getSubViewsBlock(self); - return [NSArray arrayWithArray:all]; -} - -@end - -#pragma mark - DebugSlider - -@interface DebugSlider : UIView -@property void (^touchMoveBlock)(float percent); -@property void (^touchEndBlock)(); -@end - -@implementation DebugSlider - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - UITouch *touch = [touches anyObject]; - CGPoint point = [touch locationInView:self]; - float percent = point.y / self.frame.size.height; - percent = percent<0 ? percent : (percent>1 ? 1:percent); - !_touchMoveBlock ?: _touchMoveBlock(percent); -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - !_touchEndBlock ?: _touchEndBlock(); -} - -@end - -#pragma mark - DebugWindow - -@interface DebugWindow : UIWindow - -@property (nonatomic, weak) XYDebugViewManager *frameManager; - -@property (nonatomic, weak) UIView *souceView; - -@property (nonatomic, strong) UIButton *button; -@property (nonatomic, strong) DebugSlider *slider; -@property (nonatomic, strong) UIScrollView *scrollView; -@property (nonatomic, strong) NSMutableArray * debugLayers; -@end - -@implementation DebugWindow - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - _button = [UIButton buttonWithType:UIButtonTypeCustom]; - [_button setTitle:@"tap statusbar to refresh debugging..." forState:UIControlStateNormal]; - _button.backgroundColor = [UIColor redColor]; - _button.frame = CGRectMake(0, 0, SCREEN_WIDTH, 20); - _button.titleLabel.font = [UIFont systemFontOfSize:11]; - _button.layer.zPosition = MAXFLOAT; - - _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; - _scrollView.layer.zPosition = -MAXFLOAT; - _scrollView.contentSize = CGSizeMake(SCREEN_WIDTH*2,SCREEN_HEIGHT*2); - _scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); - _scrollView.backgroundColor = [UIColor whiteColor]; - _scrollView.hidden = YES; - CATransform3D transform = CATransform3DIdentity; - transform.m34 = -1.0 / 500; - _scrollView.layer.sublayerTransform = transform; - - _slider = [[DebugSlider alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-30, 40, 20, SCREEN_HEIGHT-40*2)]; - _slider.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.3]; - _slider.hidden = YES; - - typeof(self) weakSelf = self; - _slider.touchMoveBlock = ^(float percent) { - [weakSelf showDifferentLayers:percent]; - }; - _slider.touchEndBlock = ^{ - [weakSelf showAllLayer]; - }; - - [self addSubview:_scrollView]; - [self addSubview:_button]; - [self addSubview:_slider]; - self.backgroundColor = [UIColor clearColor]; - self.debugLayers = @[].mutableCopy; - self.layer.masksToBounds = YES; - } - return self; -} - -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - if (self.userInteractionEnabled==NO || self.hidden==YES || self.alpha<=0.01) { - return nil; - } else if (![self pointInside:point withEvent:event]) { - return nil; - } else if (_frameManager.isDebugging) { - if (CGRectContainsPoint(_button.frame,point)) { - return _button; - } else if (CGRectContainsPoint(_slider.frame,point) && _souceView) { - return _slider; - } else if (CGRectContainsPoint(_scrollView.frame,point) && _souceView) { - return _scrollView; - } - return nil; - } - return nil; -} - -- (void)setSouceView:(UIView *)souceView -{ - _souceView = souceView; - if (_souceView == nil) { - [[self.debugLayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; - self.scrollView.hidden = YES; - self.slider.hidden = YES; - } else { - self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); - [self scrollViewAddLayersInView:_souceView layerLevel:0 index:0]; - self.scrollView.hidden = NO; - self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); - self.slider.hidden = NO; - } -} - -- (void)scrollViewAddLayersInView:(UIView *)view layerLevel:(CGFloat)layerLevel index:(NSUInteger)index -{ - if ([view isKindOfClass:[UIView class]] && view) { - if (view.superview) { - UIView *cloneView = view.cloneView; - cloneView.layer.zPosition = -500 + (layerLevel*60+index*5); - cloneView.layer.masksToBounds = YES; - - CGRect frame = [view.superview convertRect:view.frame toView:_souceView]; - frame.origin = CGPointMake(CGRectGetMinX(frame)+SCREEN_WIDTH/2.f, CGRectGetMinY(frame)+SCREEN_HEIGHT/2.f); - cloneView.layer.frame = frame; - cloneView.layer.opacity = 0.8; - [self.debugLayers addObject:cloneView.layer]; - [self.scrollView.layer addSublayer:cloneView.layer]; - } - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - [self scrollViewAddLayersInView:obj layerLevel:layerLevel+1 index:idx]; - }]; - }); - } -} - -- (void)showDifferentLayers:(float)percent -{ - CGFloat positionMax = self.debugLayers.firstObject.zPosition; - CGFloat positionMin = positionMax; - for (CALayer *layer in self.debugLayers) { - if (layer.zPosition >= positionMax) { - positionMax = layer.zPosition; - } - if (layer.zPosition <= positionMin) { - positionMin = layer.zPosition; - } - } - // 分成20节,每节为5 - CGFloat gap = (positionMax - positionMin)/20.f; - - // 每节为5,计算当前处于那一节的layer层显示 - float num = ceil((percent * 100)/5.f); - - CGFloat upRange = positionMin + gap*num; - CGFloat dowmRange = positionMin + gap*(num-1); - - for (CALayer *layer in self.debugLayers) { - layer.opacity = (layer.zPosition>upRange || layer.zPosition* debugLayers; + +@end diff --git a/Demo/Pods/XYDebugView/XYDebugWindow.m b/Demo/Pods/XYDebugView/XYDebugWindow.m new file mode 100644 index 0000000..d017ed2 --- /dev/null +++ b/Demo/Pods/XYDebugView/XYDebugWindow.m @@ -0,0 +1,160 @@ +// +// XYDebugWindow.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugWindow.h" +#import "XYDebugViewManager.h" +#import "UIView+XYDebug.h" + +#ifndef SCREEN_WIDTH +#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width +#endif + +#ifndef SCREEN_HEIGHT +#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height +#endif + +@implementation XYDebugWindow + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _button = [UIButton buttonWithType:UIButtonTypeCustom]; + [_button setTitle:@"tap statusbar to refresh debugging..." forState:UIControlStateNormal]; + _button.backgroundColor = [UIColor redColor]; + _button.frame = CGRectMake(0, 0, SCREEN_WIDTH, 20); + _button.titleLabel.font = [UIFont systemFontOfSize:11]; + _button.layer.zPosition = MAXFLOAT; + + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _scrollView.layer.zPosition = -MAXFLOAT; + _scrollView.contentSize = CGSizeMake(SCREEN_WIDTH*2,SCREEN_HEIGHT*2); + _scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + _scrollView.backgroundColor = [UIColor whiteColor]; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.hidden = YES; + CATransform3D transform = CATransform3DIdentity; + transform.m34 = -1.0 / 500; + _scrollView.layer.sublayerTransform = transform; + + _slider = [[DebugSlider alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-30, 40, 40, SCREEN_HEIGHT-40*2)]; + _slider.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; + _slider.hidden = YES; + + typeof(self) weakSelf = self; + _slider.touchMoveBlock = ^(float percent) { + [weakSelf showDifferentLayers:percent]; + }; + _slider.touchEndBlock = ^{ + [weakSelf showAllLayer]; + }; + + [self addSubview:_scrollView]; + [self addSubview:_button]; + [self addSubview:_slider]; + self.backgroundColor = [UIColor clearColor]; + self.debugLayers = @[].mutableCopy; + self.layer.masksToBounds = YES; + } + return self; +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + if (self.userInteractionEnabled==NO || self.hidden==YES || self.alpha<=0.01) { + return nil; + } else if (![self pointInside:point withEvent:event]) { + return nil; + } else if (_frameManager.isDebugging) { + if (CGRectContainsPoint(_button.frame,point)) { + return _button; + } else if (CGRectContainsPoint(_slider.frame,point) && _souceView) { + return _slider; + } else if (CGRectContainsPoint(_scrollView.frame,point) && _souceView) { + return _scrollView; + } + return nil; + } + return nil; +} + +- (void)setSouceView:(UIView *)souceView +{ + _souceView = souceView; + if (_souceView == nil) { + [[self.debugLayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + self.scrollView.hidden = YES; + self.slider.hidden = YES; + } else { + self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + [self scrollViewAddLayersInView:_souceView layerLevel:0 index:0]; + self.scrollView.hidden = NO; + self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + self.slider.hidden = NO; + } +} + +- (void)scrollViewAddLayersInView:(UIView *)view layerLevel:(CGFloat)layerLevel index:(NSUInteger)index +{ + if ([view isKindOfClass:[UIView class]] && view) { + if (view.superview) { + UIView *cloneView = view.cloneView; + cloneView.layer.zPosition = -600 + (layerLevel*80+index*8); + cloneView.layer.masksToBounds = YES; + + CGRect frame = [view.superview convertRect:view.frame toView:_souceView]; + frame.origin = CGPointMake(CGRectGetMinX(frame)+SCREEN_WIDTH/2.f, CGRectGetMinY(frame)+SCREEN_HEIGHT/2.f); + cloneView.layer.frame = frame; + cloneView.layer.opacity = 0.8; + [self.debugLayers addObject:cloneView.layer]; + [self.scrollView.layer addSublayer:cloneView.layer]; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self scrollViewAddLayersInView:obj layerLevel:layerLevel+1 index:idx]; + }]; + }); + } +} + +- (void)showDifferentLayers:(float)percent +{ + CGFloat positionMax = self.debugLayers.firstObject.zPosition; + CGFloat positionMin = positionMax; + for (CALayer *layer in self.debugLayers) { + if (layer.zPosition >= positionMax) { + positionMax = layer.zPosition; + } + if (layer.zPosition <= positionMin) { + positionMin = layer.zPosition; + } + } + // 分成20节,每节为5 + CGFloat gap = (positionMax - positionMin)/20.f; + + // 每节为5,计算当前处于那一节的layer层显示 + float num = ceil((percent * 100)/5.f); + + CGFloat upRange = positionMin + gap*num; + CGFloat dowmRange = positionMin + gap*(num-1); + + for (CALayer *layer in self.debugLayers) { + layer.opacity = (layer.zPosition>upRange || layer.zPosition + +@interface UIColor (XYRandom) + ++ (UIColor *)randomLightColorWithAlpha:(CGFloat)alpha; + ++ (UIColor *)randomDrakColorWithAlpha:(CGFloat)alpha; + +@end + + diff --git a/XYDebugView/UIColor+XYRandom.m b/XYDebugView/UIColor+XYRandom.m new file mode 100644 index 0000000..c00f0f4 --- /dev/null +++ b/XYDebugView/UIColor+XYRandom.m @@ -0,0 +1,30 @@ +// +// UIColor+XYDebug.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "UIColor+XYRandom.h" + +@implementation UIColor (XYRandom) + ++ (UIColor *)randomLightColorWithAlpha:(CGFloat)alpha +{ + + return [UIColor colorWithRed:(arc4random()%100+155)/255.0 + green:(arc4random()%100+155)/255.0 + blue:(arc4random()%100+155)/255.0 + alpha:alpha]; +} + ++ (UIColor *)randomDrakColorWithAlpha:(CGFloat)alpha +{ + + return [UIColor colorWithRed:(arc4random()%150)/255.0 + green:(arc4random()%150)/255.0 + blue:(arc4random()%150)/255.0 + alpha:alpha]; +} +@end diff --git a/XYDebugView/UIView+XYDebug.h b/XYDebugView/UIView+XYDebug.h new file mode 100644 index 0000000..cc3df65 --- /dev/null +++ b/XYDebugView/UIView+XYDebug.h @@ -0,0 +1,19 @@ +// +// UIView+XYDebug.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugView.h" + +@interface UIView (XYDebug) + +@property (nonatomic, strong) UIColor *debugStoreOrginalColor; +@property (nonatomic, assign) BOOL hasStoreDebugColor; +@property (nonatomic, strong, readonly) CALayer *debugColorSublayer; +@property (nonatomic, strong, readonly) XYDebugCloneView *cloneView; +@property (nonatomic, copy, readonly) NSArray *debuRecurrenceAllSubviews; + +@end diff --git a/XYDebugView/UIView+XYDebug.m b/XYDebugView/UIView+XYDebug.m new file mode 100644 index 0000000..1365cd6 --- /dev/null +++ b/XYDebugView/UIView+XYDebug.m @@ -0,0 +1,86 @@ +// +// UIView+XYDebug.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "UIView+XYDebug.h" +#import + +const static char * DebugStoreUIViewBackColor = "DebugStoreUIViewBackColor"; +const static char * DebugHasStoreUIViewBackColor = "DebugHasStoreUIViewBackColor"; +const static char * DebugCloneView = "DebugCloneView"; +const static char * DebugColorSublayer = "DebugColorSublayer"; + +@implementation UIView (XYDebug) + +- (void)setDebugStoreOrginalColor:(UIColor *)debugStoreOrginalColor +{ + if ([debugStoreOrginalColor isKindOfClass:[UIColor class]] && debugStoreOrginalColor) { + objc_setAssociatedObject(self, DebugStoreUIViewBackColor, debugStoreOrginalColor, OBJC_ASSOCIATION_RETAIN); + } +} + +- (UIColor *)debugStoreOrginalColor +{ + id obj = objc_getAssociatedObject(self, DebugStoreUIViewBackColor); + if ([obj isKindOfClass:[UIColor class]]) { + return (UIColor *)obj; + } + return nil; +} + +- (CALayer *)debugColorSublayer +{ + CALayer *obj = objc_getAssociatedObject(self, DebugColorSublayer); + if ([obj isKindOfClass:[CALayer class]] && obj) { + obj.frame = self.bounds; + return obj; + } + obj = [[CALayer alloc] init]; + obj.borderColor = [[UIColor redColor] colorWithAlphaComponent:0.3].CGColor; + obj.borderWidth = 1/[UIScreen mainScreen].scale; + objc_setAssociatedObject(self, DebugColorSublayer, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return [self debugColorSublayer]; +} + +- (XYDebugCloneView *)cloneView +{ + XYDebugCloneView *obj = objc_getAssociatedObject(self, DebugCloneView); + if ([obj isKindOfClass:[XYDebugCloneView class]] && obj) { + return obj; + } + obj = [XYDebugCloneView cloneWith:self]; + obj.debugColorSublayer.frame = obj.bounds; + [obj.layer addSublayer:obj.debugColorSublayer]; + objc_setAssociatedObject(self, DebugCloneView, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return [self cloneView]; +} + +- (void)setHasStoreDebugColor:(BOOL)hasStoreDebugColor +{ + objc_setAssociatedObject(self, DebugHasStoreUIViewBackColor, @(hasStoreDebugColor), OBJC_ASSOCIATION_ASSIGN); +} + +- (BOOL)hasStoreDebugColor +{ + id obj = objc_getAssociatedObject(self, DebugHasStoreUIViewBackColor); + return [obj boolValue]; +} + +- (NSArray *)debuRecurrenceAllSubviews +{ + NSMutableArray *all = @[].mutableCopy; + void (^getSubViewsBlock)(UIView *current) = ^(UIView *current){ + [all addObject:current]; + for (UIView *sub in current.subviews) { + [all addObjectsFromArray:[sub debuRecurrenceAllSubviews]]; + } + }; + getSubViewsBlock(self); + return [NSArray arrayWithArray:all]; +} + +@end diff --git a/XYDebugView/XYDebugView.h b/XYDebugView/XYDebugView.h new file mode 100644 index 0000000..99b0518 --- /dev/null +++ b/XYDebugView/XYDebugView.h @@ -0,0 +1,24 @@ +// +// XYDebugCloneView.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import + +@interface XYDebugCloneView : UIView + ++ (XYDebugCloneView *)cloneWith:(UIView *)view; + +@end + + +@interface DebugSlider : UIView + +@property void (^touchMoveBlock)(float percent); + +@property void (^touchEndBlock)(); + +@end diff --git a/XYDebugView/XYDebugView.m b/XYDebugView/XYDebugView.m new file mode 100644 index 0000000..7ccae5b --- /dev/null +++ b/XYDebugView/XYDebugView.m @@ -0,0 +1,88 @@ +// +// XYDebugCloneView.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugView.h" +#import "UIColor+XYRandom.h" + +@interface XYDebugCloneView () + +@property(nonatomic, weak) UIView *srcView; + +@end + +@implementation XYDebugCloneView + ++ (XYDebugCloneView *)cloneWith:(UIView *)view +{ + return [[XYDebugCloneView alloc] initWithCopyView:view]; +} + +- (instancetype)initWithCopyView:(UIView *)srcView +{ + self = [super initWithFrame:srcView.frame]; + if (self) { + self.srcView = srcView; + self.backgroundColor = [UIColor randomLightColorWithAlpha:1]; + } + return self; +} + +- (void)drawRect:(CGRect)rect +{ + NSMutableArray *mArr = self.srcView.layer.sublayers.mutableCopy; + for (UIView *subview in self.srcView.subviews) { + if ([mArr containsObject:subview.layer]) { + [mArr removeObject:subview.layer]; + } + } + CALayer *newLayer = [CALayer layer]; + newLayer.contents = self.srcView.layer.contents; + newLayer.frame = self.srcView.layer.frame; + + for (CALayer *sublayer in mArr) { + CALayer *newSub = [[CALayer alloc] initWithLayer:sublayer]; + newSub.frame = sublayer.frame; + [newLayer addSublayer:newSub]; + } + [newLayer renderInContext:UIGraphicsGetCurrentContext()]; +} +@end + + +@implementation DebugSlider +{ + CALayer *_colorLayer; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + _colorLayer = [CALayer layer]; + _colorLayer.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor; + [self.layer addSublayer:_colorLayer]; + } + return self; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; + _colorLayer.frame = CGRectMake(0, 0, self.bounds.size.width, point.y); + float percent = point.y / self.frame.size.height; + percent = percent<0 ? percent : (percent>1 ? 1:percent); + !_touchMoveBlock ?: _touchMoveBlock(percent); +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + _colorLayer.frame = CGRectZero; + !_touchEndBlock ?: _touchEndBlock(); +} + +@end diff --git a/XYDebugView/XYDebugViewManager.h b/XYDebugView/XYDebugViewManager.h new file mode 100644 index 0000000..c939099 --- /dev/null +++ b/XYDebugView/XYDebugViewManager.h @@ -0,0 +1,17 @@ +// +// XYDebugViewManager.h +// QueryViolations +// +// Created by XcodeYang on 02/05/2017. +// Copyright © 2017 eclicks. All rights reserved. +// + +#import + +@interface XYDebugViewManager : NSObject + +@property (nonatomic, assign) BOOL isDebugging; + ++ (XYDebugViewManager *)sharedInstance; + +@end diff --git a/XYDebugView/XYDebugViewManager.m b/XYDebugView/XYDebugViewManager.m new file mode 100644 index 0000000..ad3eb7d --- /dev/null +++ b/XYDebugView/XYDebugViewManager.m @@ -0,0 +1,147 @@ +// +// XYDebugViewManager.m +// QueryViolations +// +// Created by XcodeYang on 02/05/2017. +// Copyright © 2017 eclicks. All rights reserved. +// + +#import "XYDebugViewManager.h" +#import "XYDebugWindow.h" +#import "UIView+XYDebug.h" +#import "UIColor+XYRandom.h" + +#pragma mark - XYDebugViewManager + +typedef NS_ENUM (NSUInteger, DebugViewState) { + DebugViewStateNone = 0, + DebugViewState2D = 1 << 0, + DebugViewState3D = 1 << 1 +}; + +@interface XYDebugViewManager () + +@property (nonatomic, strong) XYDebugWindow *assistiveWindow; +@property (nonatomic, weak) UIWindow *keyWindow; +@property (nonatomic, assign) DebugViewState debugState; + +@end + +@implementation XYDebugViewManager + ++ (XYDebugViewManager *)sharedInstance +{ + static XYDebugViewManager *instance = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + instance.isDebugging = NO; + instance.debugState = DebugViewStateNone; + instance.keyWindow = [UIApplication sharedApplication].keyWindow; + }); + return instance; +} + +- (void)setIsDebugging:(BOOL)isDebugging +{ + if (!_assistiveWindow) { + _assistiveWindow = [[XYDebugWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + _assistiveWindow.frameManager = self; + [_assistiveWindow.button addTarget:self action:@selector(debugViewBtnClick) forControlEvents:UIControlEventTouchUpInside]; + } + + _assistiveWindow.windowLevel = isDebugging ? CGFLOAT_MAX:UIWindowLevelNormal; + _assistiveWindow.button.hidden = !isDebugging; + _assistiveWindow.souceView = nil; + + if (isDebugging) { + [_assistiveWindow makeKeyAndVisible]; + if (_keyWindow) { + [_keyWindow makeKeyWindow]; + } + } else { + [_assistiveWindow resignKeyWindow]; + _assistiveWindow = nil; + [_keyWindow makeKeyAndVisible]; + } + + [self currentWindowsShowDebugView:NO]; + _debugState = DebugViewStateNone; + _isDebugging = isDebugging; +} + +- (void)debugViewBtnClick +{ + switch (self.debugState) { + case DebugViewStateNone: { + [self currentWindowsShowDebugView:YES]; + self.debugState = DebugViewState2D; + } + break; + case DebugViewState2D:{ + _assistiveWindow.souceView = [UIApplication sharedApplication].keyWindow; + self.debugState = DebugViewState3D; + } + break; + case DebugViewState3D:{ + [self currentWindowsShowDebugView:NO]; + self.assistiveWindow.souceView = nil; + self.debugState = DebugViewStateNone; + } + break; + + default: + break; + } +} + +- (void)currentWindowsShowDebugView:(BOOL)showDebugView +{ + for (UIWindow *w in [UIApplication sharedApplication].windows) { + if (w != _assistiveWindow && w != [UIApplication sharedApplication].keyWindow) { + [self traverseSubviewIn:w shouldRecoverBackColor:!showDebugView]; + } + } + [self traverseSubviewIn:[UIApplication sharedApplication].keyWindow shouldRecoverBackColor:!showDebugView]; +} + +- (void)traverseSubviewIn:(UIView *)parentView shouldRecoverBackColor:(BOOL)shouldRecoverBackColor +{ + NSMutableArray * allViews = parentView.debuRecurrenceAllSubviews.mutableCopy; + // 移除第一个view(window) + [allViews removeObjectAtIndex:0]; + + if (shouldRecoverBackColor) { + // 回复原貌 + for (UIView *subview in allViews) { + if (!subview.hasStoreDebugColor) { return; } + subview.backgroundColor = subview.debugStoreOrginalColor ?: [UIColor clearColor]; + subview.hasStoreDebugColor = NO; + subview.layer.borderWidth = CGFLOAT_MIN; + if (subview.debugColorSublayer.superlayer) { + [subview.debugColorSublayer removeFromSuperlayer]; + } + } + } else { + // 追加debug + for (UIView *subview in allViews) { + + if (subview.hasStoreDebugColor || subview==_assistiveWindow.button) { + return; + } + subview.debugStoreOrginalColor = subview.backgroundColor; + subview.hasStoreDebugColor = YES; + if (!CGRectEqualToRect(subview.bounds, [UIScreen mainScreen].bounds)) { + subview.backgroundColor = [UIColor randomLightColorWithAlpha:0.6]; + } + + // 添加view的frame边框 + if (!subview.debugColorSublayer.superlayer) { + [subview.layer addSublayer:subview.debugColorSublayer]; + } + } + } +} + +@end diff --git a/XYDebugView/XYDebugWindow.h b/XYDebugView/XYDebugWindow.h new file mode 100644 index 0000000..fc2cb2d --- /dev/null +++ b/XYDebugView/XYDebugWindow.h @@ -0,0 +1,21 @@ +// +// XYDebugWindow.h +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugView.h" + +@class XYDebugViewManager; +@interface XYDebugWindow : UIWindow + +@property (nonatomic, weak) XYDebugViewManager *frameManager; +@property (nonatomic, weak) UIView *souceView; +@property (nonatomic, strong) UIButton *button; +@property (nonatomic, strong) DebugSlider *slider; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) NSMutableArray * debugLayers; + +@end diff --git a/XYDebugView/XYDebugWindow.m b/XYDebugView/XYDebugWindow.m new file mode 100644 index 0000000..d017ed2 --- /dev/null +++ b/XYDebugView/XYDebugWindow.m @@ -0,0 +1,160 @@ +// +// XYDebugWindow.m +// Pods +// +// Created by XcodeYang on 25/05/2017. +// +// + +#import "XYDebugWindow.h" +#import "XYDebugViewManager.h" +#import "UIView+XYDebug.h" + +#ifndef SCREEN_WIDTH +#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width +#endif + +#ifndef SCREEN_HEIGHT +#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height +#endif + +@implementation XYDebugWindow + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _button = [UIButton buttonWithType:UIButtonTypeCustom]; + [_button setTitle:@"tap statusbar to refresh debugging..." forState:UIControlStateNormal]; + _button.backgroundColor = [UIColor redColor]; + _button.frame = CGRectMake(0, 0, SCREEN_WIDTH, 20); + _button.titleLabel.font = [UIFont systemFontOfSize:11]; + _button.layer.zPosition = MAXFLOAT; + + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _scrollView.layer.zPosition = -MAXFLOAT; + _scrollView.contentSize = CGSizeMake(SCREEN_WIDTH*2,SCREEN_HEIGHT*2); + _scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + _scrollView.backgroundColor = [UIColor whiteColor]; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.hidden = YES; + CATransform3D transform = CATransform3DIdentity; + transform.m34 = -1.0 / 500; + _scrollView.layer.sublayerTransform = transform; + + _slider = [[DebugSlider alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-30, 40, 40, SCREEN_HEIGHT-40*2)]; + _slider.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; + _slider.hidden = YES; + + typeof(self) weakSelf = self; + _slider.touchMoveBlock = ^(float percent) { + [weakSelf showDifferentLayers:percent]; + }; + _slider.touchEndBlock = ^{ + [weakSelf showAllLayer]; + }; + + [self addSubview:_scrollView]; + [self addSubview:_button]; + [self addSubview:_slider]; + self.backgroundColor = [UIColor clearColor]; + self.debugLayers = @[].mutableCopy; + self.layer.masksToBounds = YES; + } + return self; +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + if (self.userInteractionEnabled==NO || self.hidden==YES || self.alpha<=0.01) { + return nil; + } else if (![self pointInside:point withEvent:event]) { + return nil; + } else if (_frameManager.isDebugging) { + if (CGRectContainsPoint(_button.frame,point)) { + return _button; + } else if (CGRectContainsPoint(_slider.frame,point) && _souceView) { + return _slider; + } else if (CGRectContainsPoint(_scrollView.frame,point) && _souceView) { + return _scrollView; + } + return nil; + } + return nil; +} + +- (void)setSouceView:(UIView *)souceView +{ + _souceView = souceView; + if (_souceView == nil) { + [[self.debugLayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + self.scrollView.hidden = YES; + self.slider.hidden = YES; + } else { + self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + [self scrollViewAddLayersInView:_souceView layerLevel:0 index:0]; + self.scrollView.hidden = NO; + self.scrollView.contentOffset = CGPointMake(SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0); + self.slider.hidden = NO; + } +} + +- (void)scrollViewAddLayersInView:(UIView *)view layerLevel:(CGFloat)layerLevel index:(NSUInteger)index +{ + if ([view isKindOfClass:[UIView class]] && view) { + if (view.superview) { + UIView *cloneView = view.cloneView; + cloneView.layer.zPosition = -600 + (layerLevel*80+index*8); + cloneView.layer.masksToBounds = YES; + + CGRect frame = [view.superview convertRect:view.frame toView:_souceView]; + frame.origin = CGPointMake(CGRectGetMinX(frame)+SCREEN_WIDTH/2.f, CGRectGetMinY(frame)+SCREEN_HEIGHT/2.f); + cloneView.layer.frame = frame; + cloneView.layer.opacity = 0.8; + [self.debugLayers addObject:cloneView.layer]; + [self.scrollView.layer addSublayer:cloneView.layer]; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self scrollViewAddLayersInView:obj layerLevel:layerLevel+1 index:idx]; + }]; + }); + } +} + +- (void)showDifferentLayers:(float)percent +{ + CGFloat positionMax = self.debugLayers.firstObject.zPosition; + CGFloat positionMin = positionMax; + for (CALayer *layer in self.debugLayers) { + if (layer.zPosition >= positionMax) { + positionMax = layer.zPosition; + } + if (layer.zPosition <= positionMin) { + positionMin = layer.zPosition; + } + } + // 分成20节,每节为5 + CGFloat gap = (positionMax - positionMin)/20.f; + + // 每节为5,计算当前处于那一节的layer层显示 + float num = ceil((percent * 100)/5.f); + + CGFloat upRange = positionMin + gap*num; + CGFloat dowmRange = positionMin + gap*(num-1); + + for (CALayer *layer in self.debugLayers) { + layer.opacity = (layer.zPosition>upRange || layer.zPosition