Наблюдение за изменениями анимированных свойств в CALayer

У меня есть CABasicAnimationанимация, CALayerнапример, свойство bounds.origin. Я хочу быть в состоянии наблюдать изменение свойства с течением времени, но на самом деле не нашел метод, который работает на 100%.

  1. Я попытался с помощью КВО (наблюдение ключ-значение) на presentationLayer«s bounds.originключевого ресурса. Система жалуется, что объект освобождается до освобождения его наблюдателей, что заставляет меня думать, что уровень представления является только временным. Наблюдение presentationLayer.bounds.originв качестве ключевого пути не работает.

  2. Я попытался создать свойство на другом слое и анимировать это, например, объявив @propertyи сделав его @dynamicна этом слое. Однако это новое свойство изменяется только при доступе к слою презентации (например, в конце анимации), оно не обновляется во время работы анимации.

  3. Я использовал needsDisplayForKeyсвойство №2, которое вызывает обновления во время анимации, но для этих проблем:

    • это работает только если CALayerимеет ненулевой кадр. Поскольку этот слой может быть CAShapeLayer или подклассом, он может иметь нулевой кадр.
    • похоже, что это срабатывает setNeedsDisplayдля этого слоя, но поскольку я на самом деле не рисую этот слой, а только отслеживаю изменение свойства, я не хочу, чтобы он перерисовывался.
  4. Я попытался планировать NSTimer, и в таймере обратного вызова образец presentationLayer. Это также работает, но для этих проблем:

    • Таймер, вероятно, будет немного не синхронизирован с обновлением анимации.
    • Так как иногда оригинальная анимация вытесняется другой анимацией, трудно заставить таймер срабатывать, когда анимация запущена и только когда анимация запущена.

Какие-либо предложения? Все это будет на iPhoneOS 3.0 / 3.1.

13.10.2009 00:56:26
2 ОТВЕТА
РЕШЕНИЕ

Я думаю, что вы назвали все возможности. На самом деле, я даже не знал о № 2 и № 3, и я написал книгу о базовой анимации . ;-)

КВО не доступен для этих свойств. Было бы неплохо, если бы это было так, но я полагаю, что причина этого связана с накладными расходами. Значение будет обновляться очень часто и придется перезванивать любым наблюдателям.

Во всяком случае, я считаю NSTimer наиболее надежным подходом, но теперь я не уверен в том, что вы сказали. Что заставляет вас думать, что таймер не синхронизирован? Почему трудно заставить таймер срабатывать только во время анимации? Разве вы не можете просто проверить условие, которое вы хотите в обратном вызове таймера, а затем ничего не делать, если условие не выполняется?

Наилучшие пожелания.

5
13.10.2009 03:37:59
NSTimers запускаются независимо от того, когда обновляются фактические слои, они всегда будут немного позади или перед шагом анимации слоя. То, что мне нужно, это получать уведомления одновременно с анимацией слоя. Лучше всего использовать CADisplayLink (только для iPhone 3.1) или создать искусственный слой с опцией № 3 для получения уведомлений. В конце концов, поскольку среда настолько динамична, я отказался от использования Core Animation для этого - теперь я использую NSTimer или CADisplayLink для автоматической прокрутки.
Glen Low 14.10.2009 21:57:58
Когда я выполняю автопрокрутку, иногда в слое, который я заменяю, присутствует существующая анимация автопрокрутки, а иногда первоначальная анимация должна быть задержана на 1/2 секунды. Таким образом, трудно понять, когда запускается настоящая анимация. Обратные вызовы делегата CAAnimation также не происходят мгновенно, поэтому есть вероятность, что любой код, зависящий от него, будет не синхронизирован с тем, что уже произошло в анимированном слое.
Glen Low 14.10.2009 22:04:52
См. Например: developer.apple.com/mac/library/qa/qa2004/qa1385.html . В документе Apple говорится: «NSTimer - это таймер общего назначения. Это не таймер, привязанный к устройству отображения. Интервал и момент запуска таймера не имеют отношения к тому, когда происходит вертикальное обновление. Это означает, что простой подход создание таймера с частотой 60,0 Гц обречено на неудачу - таймер будет дрейфовать по отношению к фактической частоте обновления, и вы потеряете или удвоите количество кадров. Это также означает, что таймер вызывает приложение в произвольную точку в обновить ... "
Glen Low 14.10.2009 22:08:54
Этот ответ выглядит хорошо для меня: stackoverflow.com/questions/18827973/…
eonist 20.02.2016 20:43:54

Попробуйте использовать CADisplayLink, который предназначен для синхронизации с циклом анимации. Дополнительная информация: https://ashfurrow.com/blog/animating-views-with-cadisplaylink/

5
16.12.2015 22:22:21