はじめに
UILabelで数値をアニメーションしてカウントしたい場合の処理を
CADisplayLinkを使用して実装してみます。
UILabelサブクラスの作成
UILabelのサブクラスを作成します。例ではPMAnimationLabelという名前にしました。
そしてアニメーションを実行するメソッド(animationFromwithDuration:)を追加します。
PMAnimationLabel.h
@interface PMAnimationLabel : UILabel
-(void)animationFrom:(float)fromValue to:(float)toValue withDuration:(NSTimeInterval)duration;
@end
アニメーション処理の実装
PMAnimationLabel.mファイルにアニメーション処理を実装していきます。
PMAnimationLabel.m
//プロパティ
@interface PMAnimationLabel()
@property (nonatomic, assign) float startValue,endValue,rate,totaltime;
@property (nonatomic, assign) CFTimeInterval startTime;
@end
@implementation PMAnimationLabel
#pragma mark -- Class Method --
-(void)animationFrom:(float)fromValue to:(float)toValue withDuration:(NSTimeInterval)duration{
self.startValue = fromValue; //アニメーション開始時の値
self.endValue = toValue; //アニメーション終了時の値
self.totaltime = duration; //アニメーションの時間
self.text = [self getTextFromProgress:self.startValue];
//CADisplayLinkの生成とコールバックの登録
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateValue:)];
self.startTime = CACurrentMediaTime();
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
#pragma mark -- Private Method --
-(void)updateValue:(CADisplayLink *)link{
float dt = ([link timestamp] - self.startTime) / self.totaltime;
if (dt >= 1.0) {
self.text = [self getTextFromProgress:self.endValue];
[link removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
return;
}
float current = (self.endValue - self.startValue) * dt + self.startValue;
self.text = [self getTextFromProgress:current];
}
-(NSString *)getTextFromProgress:(CGFloat)progress{
return [NSString stringWithFormat:@"%i",percentage];
}
@end
アニメーションの実行
PMAnimationLabelを使用したいViewなどに追加してアニメーション用のメソッドを呼び出します。
(frameの設定、addSubView:などの処理は割愛します。)
PMAnimationLabel *animationLabel = [PMAnimationLabel new];
[animationLabel animationFrom:0 to:100 withDuration:3.0];
終わりに
CADisplayLinkはディスプレイのリフレッシュに同期してRunLoopを発生させるもののようで、
NSTimerと似たような実装が可能ですが、定期的な処理を実行する場合はCADisplayLinkの方が適切なようです。
(ここは自分もよく調べられてないので自信があまりないですが。。。)