Повернуть UIImageView по часовой стрелке

Это должно быть просто, но у меня возникают проблемы с поворотом UIImageView на 360 градусов, повторяющимся навсегда.

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^{
    self.reloadButton.imageView.transform = CGAffineTransformRotate(self.reloadButton.imageView.transform, -M_PI);
} completion:^(BOOL finished) {

}];

Согласно документам, подпись угла I, проходящего до CGAffineTransformRotate, определяет направление вращения, но приведенный выше код вращается против часовой стрелки. То же самое с M_PI.

Угол в радианах, по которому эта матрица вращает координату системных осей. В iOS положительное значение указывает против часовой стрелки вращение и отрицательное значение указывает вращение по часовой стрелке. В Mac OS X, положительное значение указывает вращение по часовой стрелке и отрицательное значение указывает вращение против часовой стрелки.

Ответ 1

Кристоф уже идет правильным путем, но есть гораздо лучший способ, чтобы он вращался, не переустанавливая его в делегатах анимации каждый раз, когда он заканчивается. Это просто неправильно.

Просто установите для свойства repeatCount вашей анимации значение HUGE_VALF.

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.fromValue = @0.0f;
animation.toValue = @(2*M_PI);
animation.duration = 0.5f;             // this might be too fast
animation.repeatCount = HUGE_VALF;     // HUGE_VALF is defined in math.h so import it
[self.reloadButton.imageView.layer addAnimation:animation forKey:@"rotation"];

Как указано в документации, это заставит анимацию повторять навсегда.

Ответ 2

Извините пропущенную первую часть, представление вращается только отлично, используя меньший угол:

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^{
        redView.transform = CGAffineTransformRotate(redView.transform, M_PI_2);
    } completion:^(BOOL finished) {

    }];

Я не мог найти сколько-нибудь значимых объяснений, почему он терпит неудачу с M_PI.

Ответ 3

Я столкнулся с той же проблемой некоторое время назад. Я не помню причину этой проблемы, но это мое решение:

/**
 * Incrementally rotated the arrow view by a given angle.
 *
 * @param degrees Angle in degrees.
 * @param duration Duration of the rotation animation.
 */
- (void)rotateArrowViewByAngle:(CGFloat)degrees
                  withDuration:(NSTimeInterval)duration {

    CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    spinAnimation.fromValue = [NSNumber numberWithFloat:self.currentAngle / 180.0 * M_PI];
    spinAnimation.toValue = [NSNumber numberWithFloat:degrees / 180.0 * M_PI];
    spinAnimation.duration = duration;
    spinAnimation.cumulative = YES;
    spinAnimation.additive = YES;
    spinAnimation.removedOnCompletion = NO;
    spinAnimation.delegate = self;
    spinAnimation.fillMode = kCAFillModeForwards;

    [self.arrowView.layer addAnimation:spinAnimation forKey:@"spinAnimation"];

    self.currentAngle = degrees;
}

а затем вы можете использовать методы делегата

- (void)animationDidStart:(CAAnimation *)theAnimation
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag

вращение держит его вращением. Кроме того, параметры степени и продолжительности могут быть действительно большими числами... если этого достаточно.

UPDATE:
Как указано yinkou,

spinAnimation.repeatCount = HUGE_VALF;     // HUGE_VALF is defined in math.h so import it 

лучше, чем перезапустить анимацию в делегате.

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ:
self.currentAngle - свойство, запоминающее текущее окончательное вращение.
Мне нужно было, чтобы представление поворачивалось влево и вправо.

Ответ 4

Я написал для этого категорию UIImageView: https://gist.github.com/alexhajdu/5658543.

Просто используйте:

[_myImageView rotate360WithDuration:1.0 repeatCount:0]; //0 for infinite loop