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`. diff --git a/UICountingLabel.h b/UICountingLabel.h old mode 100644 new mode 100755 index 6814800..c840454 --- 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) NSTimeInterval 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..6cf3b7c --- a/UICountingLabel.m +++ b/UICountingLabel.m @@ -94,20 +94,32 @@ @interface UICountingLabel () @property NSTimeInterval totalTime; @property float easingRate; -@property (nonatomic, strong) UILabelCounter* counter; +@property (nonatomic, weak) 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,44 @@ -(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]; + 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)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:(NSTimer *)timer { + // 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 +217,29 @@ - (void)setTextValue:(float)value } } -- (void)runCompletionBlock -{ - if(self.completionBlock != nil) - { - self.completionBlock(); - self.completionBlock = nil; +- (void)setFormat:(NSString *)format { + _format = format; + // update label with new format + [self setTextValue:self.currentValue]; +} + +- (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