From 2211baf492c28ea432160eff840615ab5763e716 Mon Sep 17 00:00:00 2001 From: Rinat Khanov Date: Sat, 26 Jul 2014 17:54:46 +0400 Subject: [PATCH 1/4] Add currentValue and common convenient methods --- UICountingLabel.h | 10 ++++- UICountingLabel.m | 96 +++++++++++++++++++++++++++++++---------------- 2 files changed, 72 insertions(+), 34 deletions(-) mode change 100644 => 100755 UICountingLabel.h mode change 100644 => 100755 UICountingLabel.m diff --git a/UICountingLabel.h b/UICountingLabel.h old mode 100644 new mode 100755 index 6814800..d18698e --- a/UICountingLabel.h +++ b/UICountingLabel.h @@ -15,14 +15,22 @@ typedef NSAttributedString* (^UICountingLabelAttributedFormatBlock)(float value) @property (nonatomic, strong) NSString *format; @property (nonatomic, assign) UILabelCountingMethod method; +@property (nonatomic, assign) CGFloat animationDuration; @property (nonatomic, copy) UICountingLabelFormatBlock formatBlock; @property (nonatomic, copy) UICountingLabelAttributedFormatBlock attributedFormatBlock; @property (nonatomic, copy) void (^completionBlock)(); - -(void)countFrom:(float)startValue to:(float)endValue; -(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterval)duration; +-(void)countFromCurrentValueTo:(float)endValue; +-(void)countFromCurrentValueTo:(float)endValue withDuration:(NSTimeInterval)duration; + +-(void)countFromZeroTo:(float)endValue; +-(void)countFromZeroTo:(float)endValue withDuration:(NSTimeInterval)duration; + +- (CGFloat)currentValue; + @end diff --git a/UICountingLabel.m b/UICountingLabel.m old mode 100644 new mode 100755 index 163e53d..4b4865d --- a/UICountingLabel.m +++ b/UICountingLabel.m @@ -94,20 +94,32 @@ @interface UICountingLabel () @property NSTimeInterval totalTime; @property float easingRate; +@property (nonatomic, strong) NSTimer *timer; @property (nonatomic, strong) UILabelCounter* counter; @end @implementation UICountingLabel --(void)countFrom:(float)value to:(float)endValue -{ - [self countFrom:value to:endValue withDuration:2.0f]; +-(void)countFrom:(float)value to:(float)endValue { + + if (self.animationDuration == 0.0f) { + self.animationDuration = 2.0f; + } + + [self countFrom:value to:endValue withDuration:self.animationDuration]; } --(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterval)duration -{ - if(duration == 0.0){ +-(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterval)duration { + + self.startingValue = startValue; + self.destinationValue = endValue; + + // remove any (possible) old timers + [self.timer invalidate]; + self.timer = nil; + + if (duration == 0.0) { // No animation [self setTextValue:endValue]; [self runCompletionBlock]; @@ -115,8 +127,6 @@ -(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterv } self.easingRate = 3.0f; - self.startingValue = startValue; - self.destinationValue = endValue; self.progress = 0; self.totalTime = duration; self.lastUpdate = [NSDate timeIntervalSinceReferenceDate]; @@ -142,33 +152,43 @@ -(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterv self.counter.rate = 3.0f; - NSTimer* timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue:) userInfo:nil repeats:YES]; - [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - [[NSRunLoop mainRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; + self.timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue) userInfo:nil repeats:YES]; + [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; + [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode]; } --(void)updateValue:(NSTimer*)timer -{ +- (void)countFromCurrentValueTo:(float)endValue { + [self countFrom:[self currentValue] to:endValue]; +} + +- (void)countFromCurrentValueTo:(float)endValue withDuration:(NSTimeInterval)duration { + [self countFrom:[self currentValue] to:endValue withDuration:duration]; +} + +- (void)countFromZeroTo:(float)endValue { + [self countFrom:0.0f to:endValue]; +} + +- (void)countFromZeroTo:(float)endValue withDuration:(NSTimeInterval)duration { + [self countFrom:0.0f to:endValue withDuration:duration]; +} + +-(void)updateValue { + // update progress NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; self.progress += now - self.lastUpdate; self.lastUpdate = now; - - if(self.progress >= self.totalTime) - { - [timer invalidate]; + + if (self.progress >= self.totalTime) { + [self.timer invalidate]; + self.timer = nil; self.progress = self.totalTime; } - - float percent = self.progress / self.totalTime; - float updateVal =[self.counter update:percent]; - float value = self.startingValue + (updateVal * (self.destinationValue - self.startingValue)); - - - [self setTextValue:value]; - - if(self.progress == self.totalTime) - { + + [self setTextValue:[self currentValue]]; + + if (self.progress == self.totalTime) { [self runCompletionBlock]; } } @@ -196,13 +216,23 @@ - (void)setTextValue:(float)value } } -- (void)runCompletionBlock -{ - if(self.completionBlock != nil) - { - self.completionBlock(); - self.completionBlock = nil; +- (void)runCompletionBlock { + + if (self.completionBlock) { + self.completionBlock(); + self.completionBlock = nil; + } +} + +- (CGFloat)currentValue { + + if (self.progress >= self.totalTime) { + return self.destinationValue; } + + CGFloat percent = self.progress / self.totalTime; + CGFloat updateVal = [self.counter update:percent]; + return self.startingValue + (updateVal * (self.destinationValue - self.startingValue)); } @end From 05219a807961c87da0a0a064a262392086adf013 Mon Sep 17 00:00:00 2001 From: Rinat Khanov Date: Thu, 31 Jul 2014 10:25:18 +0400 Subject: [PATCH 2/4] Update label on format reset + other fixes --- UICountingLabel.h | 2 +- UICountingLabel.m | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/UICountingLabel.h b/UICountingLabel.h index d18698e..c840454 100755 --- a/UICountingLabel.h +++ b/UICountingLabel.h @@ -15,7 +15,7 @@ typedef NSAttributedString* (^UICountingLabelAttributedFormatBlock)(float value) @property (nonatomic, strong) NSString *format; @property (nonatomic, assign) UILabelCountingMethod method; -@property (nonatomic, assign) CGFloat animationDuration; +@property (nonatomic, assign) NSTimeInterval animationDuration; @property (nonatomic, copy) UICountingLabelFormatBlock formatBlock; @property (nonatomic, copy) UICountingLabelAttributedFormatBlock attributedFormatBlock; diff --git a/UICountingLabel.m b/UICountingLabel.m index 4b4865d..4ca2676 100755 --- a/UICountingLabel.m +++ b/UICountingLabel.m @@ -95,7 +95,7 @@ @interface UICountingLabel () @property float easingRate; @property (nonatomic, strong) NSTimer *timer; -@property (nonatomic, strong) UILabelCounter* counter; +@property (nonatomic, strong) UILabelCounter *counter; @end @@ -152,7 +152,7 @@ -(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterv self.counter.rate = 3.0f; - self.timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue) userInfo:nil repeats:YES]; + self.timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue:) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode]; } @@ -173,7 +173,7 @@ - (void)countFromZeroTo:(float)endValue withDuration:(NSTimeInterval)duration { [self countFrom:0.0f to:endValue withDuration:duration]; } --(void)updateValue { +- (void)updateValue:(NSTimer *)timer { // update progress NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; @@ -216,6 +216,12 @@ - (void)setTextValue:(float)value } } +- (void)setFormat:(NSString *)format { + _format = format; + // update label with new format + [self setTextValue:self.currentValue]; +} + - (void)runCompletionBlock { if (self.completionBlock) { From fc1e0c027f9ad9f26ae951d403853a72d8d2e994 Mon Sep 17 00:00:00 2001 From: Rinat Khanov Date: Thu, 31 Jul 2014 10:45:28 +0400 Subject: [PATCH 3/4] Update README --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 82fa06e..8b0e60c 100644 --- a/README.md +++ b/README.md @@ -33,18 +33,31 @@ Optionally, set the mode. The default is `UILabelCountingMethodEaseInOut`, whic When you want the label to start counting, just call: - [myLabel countFrom:0 to:100]; + [myLabel countFrom:50 to:100]; You can also specify the duration. The default is 2.0 seconds. - [myLabel countFrom:0 to:100 withDuration:5.0f]; + [myLabel countFrom:50 to:100 withDuration:5.0f]; + +Additionally, there is `animationDuration` property which you can use to override the default animation duration. + + myLabel.animationDuration = 1.0; + +You can use common convinient methods for counting, such as: + + [myLabel countFromCurrentValueTo:100]; + [myLabel countFromZeroTo:100]; -The full signature is: +Behind the scenes, these convinient methods use one base method, which has the following full signature: [myLabel countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterval)duration]; +You can get current value of your label using `-currentValue` method (works correctly in the process of animation too): + + CGFloat currentValue = [myLabel currentValue]; + ## Formats ##### When you set the `format` property, the label will look for the presence of `%(.*)d` or `%(.*)i`, and if found, will cast the value to `int` before formatting the string. Otherwise, it will format it using a `float`. From 52c7e244110316cb3f82186026180e224e16fb3c Mon Sep 17 00:00:00 2001 From: Rinat Khanov Date: Thu, 31 Jul 2014 10:54:54 +0400 Subject: [PATCH 4/4] Make timer reference weak (prevent retain cycle) --- UICountingLabel.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/UICountingLabel.m b/UICountingLabel.m index 4ca2676..6cf3b7c 100755 --- a/UICountingLabel.m +++ b/UICountingLabel.m @@ -94,7 +94,7 @@ @interface UICountingLabel () @property NSTimeInterval totalTime; @property float easingRate; -@property (nonatomic, strong) NSTimer *timer; +@property (nonatomic, weak) NSTimer *timer; @property (nonatomic, strong) UILabelCounter *counter; @end @@ -152,9 +152,10 @@ -(void)countFrom:(float)startValue to:(float)endValue withDuration:(NSTimeInterv self.counter.rate = 3.0f; - self.timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue:) userInfo:nil repeats:YES]; - [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; - [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode]; + NSTimer *timer = [NSTimer timerWithTimeInterval:(1.0f/30.0f) target:self selector:@selector(updateValue:) userInfo:nil repeats:YES]; + [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + [[NSRunLoop mainRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; + self.timer = timer; } - (void)countFromCurrentValueTo:(float)endValue {