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

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

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

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

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

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

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

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

3 ответа

Решение

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

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

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

С уважением.

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

Лучшее решение для меня - использовать одновременно CABasicAnimation и CADisplayLink. Вы можете наблюдать за изменениями при запуске анимации и заканчивать по ее окончании. Вы также можете рассчитать каждый шаг, но обратите внимание на временную логику. Он будет работать, когда вы используете линейную синхронизацию. Или вам нужно подготовить аналогичную логику для вашего класса на основе CADisplayLink (преобразование согласуется с изменениями времени).

Другие вопросы по тегам