Я не могу говорить с различиями iOS 5.xv 6.x, но когда я использую CADisplayLink
, я никогда не записываю такие вещи, как «move x pixels/points» на каждой итерации, но я смотрю на timestamp
(или, точнее, дельта между моим начальным timestamp
и текущим timestamp
) и вычислить местоположение в зависимости от того, сколько времени прошло, а не от того, сколько кадров прошло. Таким образом, частота кадров не влияет на скорость движения, а скорее на гладкость. (А разница между 30 и 29, вероятно, будет неразличимы.)
Цитаты из CADisplayLink Class Reference:
После того, как связь дисплея связана с циклом выполнения, селектор на цели вызывается, когда необходимо обновить содержимое экрана. Целевой объект может считывать свойство timestamp ссылочной ссылки для отображения времени отображения предыдущего кадра. Например, приложение, которое отображает фильмы, может использовать временную метку для вычисления следующего кадра видео. Приложение, которое выполняет собственные анимации, может использовать временную метку, чтобы определить, где и как отображаемые объекты появляются в предстоящем кадре. Свойство duration предоставляет время между кадрами. Вы можете использовать это значение в своем приложении, чтобы рассчитать частоту кадров дисплея, приблизительное время отображения следующего кадра и настроить поведение чертежа, чтобы следующий кадр был подготовлен вовремя для отображения.
В качестве случайного примера here я анимировать UIBezierPath
с использованием количества секунд, прошедших в качестве параметра.
Или, наоборот, если вы имеете дело с последовательностью UIImage
кадров, можно рассчитать количество кадров следующим образом:
@property (nonatomic) CFTimeInterval firstTimestamp;
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
if (!self.firstTimestamp)
self.firstTimestamp = displayLink.timestamp;
CFTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp);
NSInteger frameNumber = (NSInteger)(elapsed * kFramesPerSecond) % kMaxNumberOfFrames;
// now do whatever you want with this frame number
}
Или, еще лучше, чтобы избежать риска потерять кадр, идти вперед и пусть это работает со скоростью 60 кадров в секунду и просто определяет, нуждается ли кадр в обновлении, и таким образом вы уменьшите риск падения кадра.
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
if (!self.firstTimestamp)
self.firstTimestamp = displayLink.timestamp;
CFTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp);
NSInteger frameNumber = (NSInteger)(elapsed * kFramesPerSecond) % kMaxNumberOfFrames;
if (frameNumber != self.lastFrame)
{
// do whatever you want with this frame number
...
// now update the "lastFrame" number property
self.lastFrame = frameNumber;
}
}
Но часто, номера кадров не нужны вообще.Например, чтобы переместить UIView
в круг, вы могли бы сделать что-то вроде:
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
if (!self.firstTimestamp)
self.firstTimestamp = displayLink.timestamp;
CFTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp);
self.animatedView.center = [self centerAtElapsed:elapsed];
}
- (CGPoint)centerAtElapsed:(CFTimeInterval)elapsed
{
CGFloat radius = self.view.bounds.size.width/2.0;
return CGPointMake(radius + sin(elapsed) * radius,
radius + cos(elapsed) * radius);
}
Кстати, если вы используете инструменты для измерения частоты кадров, это может показаться медленнее, чем на самом деле будет на Устройство. Для комментария мата, для точной частоты кадров, вы должны измерять его программно на реальном устройстве с помощью сборки релиза.
Отличная идея! Итак, по методу onTick, мне присваивается метка времени, а затем на следующем, я снова отметю время, а затем сравните, чтобы узнать, есть ли разница в 0.03333 секунды? Что, если я этого не сделаю? Можете ли вы рассказать о своей концепции? – objectiveccoder001
@ objectiveccoder001 Если есть какая-то причина, по которой вам абсолютно необходимо 30 кадров в секунду, тогда да, вы могли бы сделать что-то подобное. См. Мой пример кода, который может определять номер кадра в зависимости от прошедшего времени. Однако многие анимации вам не нужно делать, но вы можете просто вычислить новую позицию на основе прошедшего времени, и нет причин, по которым она ограничена 30 кадрами в секунду (против 29 против 59 против и т. Д.). – Rob
УДИВИТЕЛЬНЫЙ! Огромное спасибо. Что такое kMaxNumberOfFrames? – objectiveccoder001