简体   繁体   中英

How to rotate an UIView around it's center, with 1 minute duration, 1 second intervals and a silky smooth animation?

I'm trying to rotate an UIView. This UIView represents the seconds pointer of a clock.

I need to update it every second. Like this:

- (void)startUpdates {
    _updateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(animatePointer) userInfo:nil repeats:YES];
}

Stop it when I need it to, like this:

- (void)stopUpdates {
    [_updateTimer invalidate];
    _updateTimer = nil;
}

And animate every second, from one second, to the next, like this:

- (void)animatePointer {

    NSDate *now = [NSDate date];
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSSecondCalendarUnit fromDate:now];

    float angleForSeconds = (float)[components second] / 60.0;

    [UIView animateWithDuration:1.0 animations:^(void){
        _pointerGlow.layer.transform = CATransform3DMakeRotation((M_PI * 2) * angleForSeconds, 0, 0, 1);
    }];

}

This does work, but it's not smooth. It stops for a fraction of a second, every second, like a tipical wall clock would. Nice, but not what I'm going for.

Is there any way I could make this animation silky smooth?

You could try it with a CADisplayLink which is tied to the display refresh rate of 60/second. The code looks like this (note that I didn't add any logic to stop the display link, but I put in the method that you would call if you wanted to):

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CFTimeInterval firstTimestamp;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self startDisplayLink];
}


- (void)startDisplayLink {
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink {
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink {
    if (!self.firstTimestamp) self.firstTimestamp = displayLink.timestamp;
    NSTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp);
    self.arrow.layer.transform = CATransform3DMakeRotation((M_PI * 2) * elapsed/60, 0, 0, 1);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM