From 3e8437ae559487362fae3525beb79c534c213a51 Mon Sep 17 00:00:00 2001
From: 单军华
Date: Thu, 12 Jul 2018 13:44:34 +0800
Subject: [PATCH] bug修复和功能优化

---
 screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m |  542 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 542 insertions(+), 0 deletions(-)

diff --git a/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m b/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m
new file mode 100755
index 0000000..ba0e7fd
--- /dev/null
+++ b/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m
@@ -0,0 +1,542 @@
+//
+//  UINavigationController+M13ProgressViewBar.m
+//  M13ProgressView
+//
+
+#import "UINavigationController+M13ProgressViewBar.h"
+#import "UIApplication+M13ProgressSuite.h"
+#import <objc/runtime.h>
+
+//Keys to set properties since one cannot define properties in a category.
+static char oldTitleKey;
+static char displayLinkKey;
+static char animationFromKey;
+static char animationToKey;
+static char animationStartTimeKey;
+static char progressKey;
+static char progressViewKey;
+static char indeterminateKey;
+static char indeterminateLayerKey;
+static char isShowingProgressKey;
+static char primaryColorKey;
+static char secondaryColorKey;
+static char backgroundColorKey;
+static char backgroundViewKey;
+
+@implementation UINavigationController (M13ProgressViewBar)
+
+#pragma mark Title
+
+- (void)setProgressTitle:(NSString *)title
+{
+    //Change the title on screen.
+    NSString *oldTitle = [self getOldTitle];
+    if (oldTitle == nil) {
+        //We haven't changed the navigation bar yet. So store the original before changing it.
+        [self setOldTitle:self.visibleViewController.navigationItem.title];
+    }
+    
+    if (title != nil) {
+        self.visibleViewController.navigationItem.title = title;
+    } else {
+        self.visibleViewController.navigationItem.title = oldTitle;
+        [self setOldTitle:nil];
+    }
+}
+
+#pragma mark Progress
+
+- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
+{
+    CADisplayLink *displayLink = [self getDisplayLink];
+    if (animated == NO) {
+        if (displayLink) {
+            //Kill running animations
+            [displayLink invalidate];
+            [self setDisplayLink:nil];
+        }
+        [self setProgress:progress];
+    } else {
+        [self setAnimationStartTime:CACurrentMediaTime()];
+        [self setAnimationFromValue:[self getProgress]];
+        [self setAnimationToValue:progress];
+        if (!displayLink) {
+            //Create and setup the display link
+            [displayLink invalidate];
+            displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateProgress:)];
+            [self setDisplayLink:displayLink];
+            [displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
+        } /*else {
+           //Reuse the current display link
+           }*/
+    }
+}
+
+- (void)animateProgress:(CADisplayLink *)displayLink
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        CGFloat dt = (displayLink.timestamp - [self getAnimationStartTime]) / [self getAnimationDuration];
+        if (dt >= 1.0) {
+            //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
+            [displayLink invalidate];
+            [self setDisplayLink:nil];
+            [self setProgress:[self getAnimationToValue]];
+            return;
+        }
+        
+        //Set progress
+        [self setProgress:[self getAnimationFromValue] + dt * ([self getAnimationToValue] - [self getAnimationFromValue])];
+        
+    });
+}
+
+- (void)finishProgress
+{
+    UIView *progressView = [self getProgressView];
+    UIView *backgroundView = [self getBackgroundView];
+    if (progressView && backgroundView) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [UIView animateWithDuration:0.1 animations:^{
+                CGRect progressFrame = progressView.frame;
+                progressFrame.size.width = self.navigationBar.frame.size.width;
+                progressView.frame = progressFrame;
+            } completion:^(BOOL finished) {
+                [UIView animateWithDuration:0.5 animations:^{
+                    progressView.alpha = 0;
+                    backgroundView.alpha = 0;
+                } completion:^(BOOL finished) {
+                    [progressView removeFromSuperview];
+                    [backgroundView removeFromSuperview];
+                    backgroundView.alpha = 1;
+                    progressView.alpha = 1;
+                    [self setTitle:nil];
+                    [self setIsShowingProgressBar:NO];
+                }];
+            }];
+        });
+    }
+}
+
+- (void)cancelProgress
+{
+    UIView *progressView = [self getProgressView];
+    UIView *backgroundView = [self getBackgroundView];
+
+    if (progressView && backgroundView) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [UIView animateWithDuration:0.5 animations:^{
+                progressView.alpha = 0;
+                backgroundView.alpha = 0;
+            } completion:^(BOOL finished) {
+                [progressView removeFromSuperview];
+                [backgroundView removeFromSuperview];
+                progressView.alpha = 1;
+                backgroundView.alpha = 1;
+                [self setTitle:nil];
+                [self setIsShowingProgressBar:NO];
+            }];
+        });
+    }
+}
+
+#pragma mark Orientation
+
+- (UIInterfaceOrientation)currentDeviceOrientation
+{
+    UIInterfaceOrientation orientation;
+
+    if ([UIApplication isM13AppExtension]) {
+        if ([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
+            orientation = UIInterfaceOrientationPortrait;
+        } else {
+            orientation = UIInterfaceOrientationLandscapeLeft;
+        }
+    } else {
+        orientation = [UIApplication safeM13SharedApplication].statusBarOrientation;
+    }
+  
+    return orientation;
+}
+
+#pragma mark Drawing
+
+- (void)showProgress
+{
+    UIView *progressView = [self getProgressView];
+    UIView *backgroundView = [self getBackgroundView];
+    
+    [UIView animateWithDuration:.1 animations:^{
+        progressView.alpha = 1;
+        backgroundView.alpha = 1;
+    }];
+    
+    [self setIsShowingProgressBar:YES];
+}
+
+- (void)updateProgress
+{
+    [self updateProgressWithInterfaceOrientation:[self currentDeviceOrientation]];
+}
+
+- (void)updateProgressWithInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    //Create the progress view if it doesn't exist
+	UIView *progressView = [self getProgressView];
+    if(!progressView)
+	{
+		progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 2.5)];
+        progressView.clipsToBounds = YES;
+        [self setProgressView:progressView];
+	}
+    
+    if ([self getPrimaryColor]) {
+        progressView.backgroundColor = [self getPrimaryColor];
+    } else {
+        progressView.backgroundColor = self.navigationBar.tintColor;
+    }
+    
+    //Create background view if it doesn't exist
+    UIView *backgroundView = [self getBackgroundView];
+    if (!backgroundView)
+    {
+        backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 2.5)];
+        backgroundView.clipsToBounds = YES;
+        [self setBackgroundView:backgroundView];
+    }
+    
+    if ([self getBackgroundColor]) {
+        backgroundView.backgroundColor = [self getBackgroundColor];
+    } else {
+        backgroundView.backgroundColor = [UIColor clearColor];
+    }
+    
+    //Calculate the frame of the navigation bar, based off the orientation.
+    UIView *topView = self.topViewController.view;
+    CGSize screenSize;
+    if (topView) {
+        screenSize = topView.bounds.size;
+    } else {
+        screenSize = [UIScreen mainScreen].bounds.size;
+    }
+    CGFloat width = 0.0;
+    CGFloat height = 0.0;
+    //Calculate the width of the screen
+    if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
+        //Use the maximum value
+        width = MAX(screenSize.width, screenSize.height);
+        if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
+            height = 32.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+        } else {
+            height = 44.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+        }
+    } else {
+        //Use the minimum value
+        width = MIN(screenSize.width, screenSize.height);
+        height = 44.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+    }
+    
+    //Check if the progress view is in its superview and if we are showing the bar.
+    if (progressView.superview == nil && [self isShowingProgressBar]) {
+        [self.navigationBar addSubview:backgroundView];
+        [self.navigationBar addSubview:progressView];
+    }
+    
+    //Layout
+    if (![self getIndeterminate]) {
+        //Calculate the width of the progress view;
+        float progressWidth = (float)width * (float)[self getProgress];
+        //Set the frame of the progress view
+        progressView.frame = CGRectMake(0, height - 2.5, progressWidth, 2.5);
+    } else {
+        //Calculate the width of the progress view
+        progressView.frame = CGRectMake(0, height - 2.5, width, 2.5);
+    }
+    backgroundView.frame = CGRectMake(0, height - 2.5, width, 2.5);
+}
+
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
+{
+    [self updateProgressWithInterfaceOrientation:toInterfaceOrientation];
+    [self drawIndeterminateWithInterfaceOrientation:toInterfaceOrientation];
+}
+
+- (void)drawIndeterminate
+{
+    [self drawIndeterminateWithInterfaceOrientation:[self currentDeviceOrientation]];
+}
+
+- (void)drawIndeterminateWithInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ([self getIndeterminate]) {
+        //Get the indeterminate layer
+        CALayer *indeterminateLayer = [self getIndeterminateLayer];
+        if (!indeterminateLayer) {
+            //Create if needed
+            indeterminateLayer = [CALayer layer];
+            [self setIndeterminateLayer:indeterminateLayer];
+        }
+        
+        //Calculate the frame of the navigation bar, based off the orientation.
+        CGSize screenSize = [UIScreen mainScreen].bounds.size;
+        CGFloat width = 0.0;
+        //Calculate the width of the screen
+        if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
+            //Use the maximum value
+            width = MAX(screenSize.width, screenSize.height);
+        } else {
+            //Use the minimum value
+            width = MIN(screenSize.width, screenSize.height);
+        }
+        
+        //Create the pattern image
+        CGFloat stripeWidth = 2.5;
+        //Start the image context
+        UIGraphicsBeginImageContextWithOptions(CGSizeMake(stripeWidth * 4.0, stripeWidth * 4.0), NO, [UIScreen mainScreen].scale);
+        //Fill the background
+        if ([self getPrimaryColor]) {
+            [[self getPrimaryColor] setFill];
+        } else {
+        [self.navigationBar.tintColor setFill];
+        }
+        UIBezierPath *fillPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, stripeWidth * 4.0, stripeWidth * 4.0)];
+        [fillPath fill];
+        //Draw the stripes
+        //Set the stripe color
+        if ([self getSecondaryColor]) {
+            [[self getSecondaryColor] setFill];
+        } else {
+            CGFloat red;
+            CGFloat green;
+            CGFloat blue;
+            CGFloat alpha;
+            [self.navigationBar.barTintColor getRed:&red green:&green blue:&blue alpha:&alpha];
+            //System set the tint color to a close to, but not non-zero value for each component. 
+            if (alpha > .05) {
+                [self.navigationBar.barTintColor setFill];
+            } else {
+                [[UIColor whiteColor] setFill];
+            }
+            
+        }
+        
+        for (int i = 0; i < 4; i++) {
+            //Create the four inital points of the fill shape
+            CGPoint bottomLeft = CGPointMake(-(stripeWidth * 4.0), stripeWidth * 4.0);
+            CGPoint topLeft = CGPointMake(0, 0);
+            CGPoint topRight = CGPointMake(stripeWidth, 0);
+            CGPoint bottomRight = CGPointMake(-(stripeWidth * 4.0) + stripeWidth, stripeWidth * 4.0);
+            //Shift all four points as needed to draw all four stripes
+            bottomLeft.x += i * (2 * stripeWidth);
+            topLeft.x += i * (2 * stripeWidth);
+            topRight.x += i * (2 * stripeWidth);
+            bottomRight.x += i * (2 * stripeWidth);
+            //Create the fill path
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:bottomLeft];
+            [path addLineToPoint:topLeft];
+            [path addLineToPoint:topRight];
+            [path addLineToPoint:bottomRight];
+            [path closePath];
+            [path fill];
+        }
+        //Retreive the image
+        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+        //Set the background of the progress layer
+        indeterminateLayer.backgroundColor = [UIColor colorWithPatternImage:image].CGColor;
+        
+        //remove any indeterminate layer animations
+        [indeterminateLayer removeAllAnimations];
+        //Set the indeterminate layer frame and add to the sub view
+        indeterminateLayer.frame = CGRectMake(0, 0, width + (4 * 2.5), 2.5);
+        UIView *progressView = [self getProgressView];
+        [progressView.layer addSublayer:indeterminateLayer];
+        //Add the animation
+        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
+        animation.duration = .1;
+        animation.repeatCount = HUGE_VALF;
+        animation.removedOnCompletion = YES;
+        animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(- (2 * 2.5) + (width / 2.0), 2.5 / 2.0)];
+        animation.toValue = [NSValue valueWithCGPoint:CGPointMake(0 + (width / 2.0), 2.5 / 2.0)];
+        [indeterminateLayer addAnimation:animation forKey:@"position"];
+    } else {
+        CALayer *indeterminateLayer = [self getIndeterminateLayer];
+        [indeterminateLayer removeAllAnimations];
+        [indeterminateLayer removeFromSuperlayer];
+    }
+}
+
+#pragma mark properties
+
+- (void)setOldTitle:(NSString *)oldTitle
+{
+    objc_setAssociatedObject(self, &oldTitleKey, self.visibleViewController.navigationItem.title, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSString *)getOldTitle
+{
+    return objc_getAssociatedObject(self, &oldTitleKey);
+}
+
+- (void)setDisplayLink:(CADisplayLink *)displayLink
+{
+    objc_setAssociatedObject(self, &displayLinkKey, displayLink, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CADisplayLink *)getDisplayLink
+{
+    return objc_getAssociatedObject(self, &displayLinkKey);
+}
+
+- (void)setAnimationFromValue:(CGFloat)animationFromValue
+{
+    objc_setAssociatedObject(self, &animationFromKey, [NSNumber numberWithFloat:(float)animationFromValue], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getAnimationFromValue
+{
+    NSNumber *number = objc_getAssociatedObject(self, &animationFromKey);
+    return number.floatValue;
+}
+
+- (void)setAnimationToValue:(CGFloat)animationToValue
+{
+    objc_setAssociatedObject(self, &animationToKey, [NSNumber numberWithFloat:(float)animationToValue], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getAnimationToValue
+{
+    NSNumber *number = objc_getAssociatedObject(self, &animationToKey);
+    return number.floatValue;
+}
+
+- (void)setAnimationStartTime:(NSTimeInterval)animationStartTime
+{
+    objc_setAssociatedObject(self, &animationStartTimeKey, [NSNumber numberWithFloat:(float)animationStartTime], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSTimeInterval)getAnimationStartTime
+{
+    NSNumber *number =  objc_getAssociatedObject(self, &animationStartTimeKey);
+    return number.floatValue;
+}
+
+- (void)setProgress:(CGFloat)progress
+{
+    if (progress > 1.0) {
+        progress = 1.0;
+    } else if (progress < 0.0) {
+        progress = 0.0;
+    }
+    objc_setAssociatedObject(self, &progressKey, [NSNumber numberWithFloat:(float)progress], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    //Draw the update
+    if ([NSThread isMainThread]) {
+        [self updateProgress];
+    } else {
+        //Sometimes UINavigationController runs in a background thread. And drawing is not thread safe.
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self updateProgress];
+        });
+    }
+}
+
+- (void)setIsShowingProgressBar:(BOOL)isShowingProgressBar
+{
+    objc_setAssociatedObject(self, &isShowingProgressKey, [NSNumber numberWithBool:isShowingProgressBar], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getProgress
+{
+    NSNumber *number =  objc_getAssociatedObject(self, &progressKey);
+    return number.floatValue;
+}
+
+- (CGFloat)getAnimationDuration
+{
+    return .3;
+}
+
+- (void)setProgressView:(UIView *)view
+{
+    objc_setAssociatedObject(self, &progressViewKey, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (UIView *)getProgressView
+{
+    return objc_getAssociatedObject(self, &progressViewKey);
+}
+
+- (void)setBackgroundView:(UIView *)view
+{
+    objc_setAssociatedObject(self, &backgroundViewKey, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (UIView *)getBackgroundView
+{
+    return objc_getAssociatedObject(self, &backgroundViewKey);
+}
+
+
+- (void)setIndeterminate:(BOOL)indeterminate
+{
+    objc_setAssociatedObject(self, &indeterminateKey, [NSNumber numberWithBool:indeterminate], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [self updateProgress];
+    [self drawIndeterminate];
+}
+
+- (BOOL)getIndeterminate
+{
+    NSNumber *number = objc_getAssociatedObject(self, &indeterminateKey);
+    return number.boolValue;
+}
+
+- (void)setIndeterminateLayer:(CALayer *)indeterminateLayer
+{
+    objc_setAssociatedObject(self, &indeterminateLayerKey, indeterminateLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CALayer *)getIndeterminateLayer
+{
+    return objc_getAssociatedObject(self, &indeterminateLayerKey);
+}
+
+- (BOOL)isShowingProgressBar
+{
+    return [objc_getAssociatedObject(self, &isShowingProgressKey) boolValue];
+}
+
+- (void)setPrimaryColor:(UIColor *)primaryColor
+{
+    objc_setAssociatedObject(self, &primaryColorKey, primaryColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [self getProgressView].backgroundColor = primaryColor;
+    [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getPrimaryColor
+{
+    return objc_getAssociatedObject(self, &primaryColorKey);
+}
+
+- (void)setSecondaryColor:(UIColor *)secondaryColor
+{
+    objc_setAssociatedObject(self, &secondaryColorKey, secondaryColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getSecondaryColor
+{
+    return objc_getAssociatedObject(self, &secondaryColorKey);
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor
+{
+    objc_setAssociatedObject(self, &backgroundColorKey, backgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getBackgroundColor
+{
+    return objc_getAssociatedObject(self, &backgroundColorKey);
+}
+
+@end

--
Gitblit v1.8.0