Это сложный вопрос. Ответ прост: используйте распознаватель панорамирования с помощью:
- (void)panBegan:(UIPanGestureRecognizer *)pan {
CGRect frame = [self frame];
_central = CGPointMake(frame.origin.x+frame.size.width/2, frame.origin.y+frame.size.height/2);
CGPoint p = [pan locationInView:[self superview]];
p.x -= _central.x;
p.y -= _central.y;
_angle = atan2(p.x, p.y);
}
- (void)panMoved:(UIPanGestureRecognizer *)pan {
CGPoint p = [pan locationInView:[self superview]]];
p.x -= _central.x;
p.y -= _central.y;
CGFloat deltaAngle = _angle - atan2(p.x, p.y);
self.transform = CGAffineTransformMakeRotation(deltaAngle + _finalAngle);
}
где _angle - угол начального касания панорамирования, а _finalAngle - сохраненный угол в конце предыдущего панорамирования.
Но: UIPanGestureRecognizer имеет свойство скорости, и вы должны использовать его в конце панорамы, чтобы продолжить вращение, как если бы циферблат имел инерцию. И, если циферблат имеет фиксированный целочисленный набор допустимых остановочных положений, то вы должны настроить кривую замедления так, чтобы она остановилась на допустимом остановке. И, если вы анимируете замедление, и пользователь запускает новый панорамирование до того, как предыдущий будет закончен, тогда вы должны настроить _finalAngle на основе воспринимаемой позиции, а не сохраненной позиции.