Вносим ясность в Core Animation.

Практически во всех приложения для iOS и Mac используется анимация явным или не явным способом. Есть даже разработчики, которые используют эту технологию, не подозревая о её существовании. Более того правильно построенная архитектура  Core Animation и Quartz сделали платформы от Apple (Mac и iOS) такими красивыми и быстрыми. Дело не в железе. Например Android пришли к похожему решению только в четвертой версии, Qt в пятой (им простительно, у них профиль пошире), Symbian вообще не пришли к такой архитектуре. Более того, многие обмануты названием этой технологии и думают, что она сделана только для анимации. Это абсолютная неправда, надеюсь у меня получится вам об этом рассказать.
Позже, когда будем знакомиться с архитектурными особенностями CA (с этого места я так буду называть Core Animation) я проведу сравнительный анализ с ближайшим конкурентом: Android и  Windows.
Вот что это такое, зачем оно сделано и главное как с ним работать я и пытаюсь объяснить вкратце в цикле статей (одной статьей невозможно обойтись).


Зачем вообще это нужно.

CA преднанзначено для того, чтоб убрать с разработчика необходимость напрямую работать с GPU для отрисовки интерфейса и не напрягать попусту CPU. Почему так важно напрягать  GPU, а не CPU. Если расшифровать, то GPU - это вычислительный центр для графики (графический процессор), а CPU - это центральный процессор общего назначения. Конечно без него не обходится в любом случае, но если с него убрать обязанности отрисовывать и просчитывать графику, то у него останется больше времени на другие задачи (реакция на прерывания, работа с сетью). 
Второй фактор - это то, что графические операции в  GPU выполняются намного быстрее и на это требуется меньше ресурсов, так как они имеют конвеерную архитектуру и ограниченный набор команд. И основная их задача - это рэндеринг и блэндинг. Скорость чтения из видеопамяти в несколько раз выше, чем из ОЗУ - это тоже играет большое значение. Ну и если графику еще держать в видеопамяти, то еще и оперативной памяти будет побольше свободной.
Но это лирика, главное - это то, что если графикой будет заниматься GPU, то система будет работать быстрее и батарейка будет кушаться меньше (если мы говорим о мобильном устройстве).
Но почему же так не делают все ? Да потому-что это не так просто, на разработку интерфейса уйдет уйма времени, особенно, если 3Д ускорение интерфейса не поддерживается на системном уровне. И просто нарисовать кнопку и отлавливать нажатие на неё - это огромное количество работы.

Но Cocoa(touch) разработчикам в этом очень круто повезло, так как все это уже сделано, благодаря Quartz, который объединяет OpenGL и интерфейс пользователя. По факту любое приложение для iOS уже отрисовывается в OpenGL и тут старается GPU. И многие, кто пишет приложения, даже об этом и не знают. В маке это опционально и работает с небольшими уточнениями (но все идет к тому, что это будет обязательно).

Core Animation помогает "оживлять" интерфейс, предлагая очень простой API для этого. Вам просто нужно задать начальные и конечные значения анимации (позицию, прозрачность, размер( и по желанию изменить параметры анимации. И всё! Очень просто. Не нужно просчитывать каждый отдельный шаг анимации, не нужно будет производить вертикальную синхронизацию с видеобуфером, не нужно будет делать двойную буферизацию и тд. 

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


Слои.

Слой - это базовая единица, с которой работает CoreAnimation. Слой - это неких холст, канвас, backing store, который хранит в себе картинку. По факту - это некий графический кэш. Но сам слой не делает ничего, он не занимается отрисовкой. И при изменении свойств слоя - вы просто меняете свойства этого объекта. А когда нужно отрисовать этот слой - эти данные объекта, вместе с закэшированным изображением передаются в GPU и там уже отрисовываются. Поэтому когда вы поменяли параметры слоя (положение, размер), то не происходит скэйлинга картинки или блэндинга дерева слоев. GPU просто перерисовывает кадр, учитывая новые свойства. Это очень важно понять, если вы не очень поняли суть - перечитайте еще раз.  Слой - это модель. Просто хранит состояние объекта и его данные, которые нужно рисовать. 
Например у нас слой с картинкой размером 100х100. Он 30 кадров отрисовывается именно такми образом. Потом мы изменили размер слоя (вернее его масштаб) и сказали, чтоб он рисовался на участке 50х50 (уменьшили в 2 раза). При этом все что произошло на уровне CPU - это мы переписали 1 значение масштаба, 4 байта. Это происходит в 1 такт процессора. А если бы мы уменьшили в размерах картинку в 2 раза, то это бы было намного дольше (провели программное масштабирование). Да и как еще один побочный эффект - это мы бы не смогли вернуть картинке первоначальное значение, в случае же со слоями, картинка у нас всегда находится в исходном состоянии.

Вот из документации картинка:

Пример из документации: Если бы мы изменили параметры UIImageView с картинкой, тогда бы автоматически вызвался метод drawRect: для отрисовки картинки с новыми параметрами. И эта перерисовка проихошла бы уже с помощью CPU, что намного хуже. 

Чет я запутался, давай пример.

Запомните, что для каждой UIView есть слой, которых хранит закэшированное состояние объекта. Возьмем текстовое поле: UILabel. Мы присвоили свойству текст значение "Тест1". Сразу после этого у этого UILbael выставляется флаг dirty, что его нужно отрисовать (еще это можно инициировать вручную, с помощью метода setNeedsDisplay). В следющем цикле main у этого UILabel вызываетмя метод drawRect, в котором уже UILabel рисует себя на слое. Тоесть формирует картинку в некой области памяти (слой). И при следующей отрисовке на экране из слоя берется уже другое значение картинки и на экране мы видим этот текст.

Этот так называемая "программная  отрисовка". 

Теперь возьмем конкретный пример. Вот у нас такая вьюха:


Красный текст мы будем анимировать программно, а зеленый с помощью CA.
Вот так будет выглядеть пример программной анимации:
А вот так с помощью CA:


Напомню, что используя программную отрисовку, мы рисуем фрейм либо раз в единицу времени (в моем случае 60 раз в секунду), либо когда приходит очередь перерисовывать интерфейс. Другими словами по факту или как получиться. В случае CA заморачиваться не нужно, просто говорим сколько времени анимация длиться и какие начальные и конечные значения.

Визуально оба UILabel движутся по экрану, но по факту движется только красный, а Зеленый как был на своей позиции, так и остался. Но его слой меняет свою позицию, поэтом на экране композитор рисует зеленый UILabel каждый раз в новой позиции. 
Чтоб убедиться, встроим такой лог:
И в итоге получим:


Позицию свою не меняет, но если будем выводить позицию слоя, то там уже значения будут меняться.
"Ну и что ?", скажете вы. А вот тут проведем тестирование с момощью Instruments.
Вот результаты тестирования только с программной анимацией:

Обратите внимание, что огромную часть времени съедает метод softwareDrawFrame, что в принципе и понятно, так как это все, что делает приложение.
А вот результаты тестирования используя CA:

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

"И там и там скорость отрисовки 60fps", может кто-то сказать. Но посмотрите на первый график, он имеет провал. Если кто-то зачем-то заберет CPU, то анимация перестанет нормально работать. Вот вам и провал. Второй минус, о котором я говорил, - это батарейка. Об этом нельзя забывать. Нельзя сажать пользователю батарейку, а то он уйдет на андроид :-)

Очень рекомендую к прочтению официальную документацию, там все понятно и доступно расписано с картинками и примерами.

Проект можно скачать на гитхабе.