Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
30
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

CADisplayLinkを使ったUILabelのアニメーション

はじめに

UILabelで数値をアニメーションしてカウントしたい場合の処理を
CADisplayLinkを使用して実装してみます。

UILabelサブクラスの作成

UILabelのサブクラスを作成します。例ではPMAnimationLabelという名前にしました。
そしてアニメーションを実行するメソッド(animationFrom:flag_to:withDuration:)を追加します。

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の方が適切なようです。
(ここは自分もよく調べられてないので自信があまりないですが。。。)

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
30
Help us understand the problem. What are the problem?