Core Animation: основе, CALayer и анимација у iOS

Аутор: IT Sectr Објављено: 2026-03-01 Време читања: 8 мин

Core Animation је Apple-ов нисконвојски фрејмворк за анимацију који ради на нивоу CALayer и обезбеђује приказивање садржаја на GPU. Core Animation је основа свих анимација у iOS и macOS: UIKit, AppKit, SceneKit и SpriteKit су изграђени на њој. Чланак објашњава архитектуру CALayer, CABasicAnimation, CATransaction и практичне технике.

Главне тачке

  • CALayer основна класа Core Animation за управљање приказивањем садржаја на GPU
  • CABasicAnimation једноставна анимација једног својства CALayer од fromValue до toValue
  • CATransaction груписање анимација у једну трансакцију са заједничким duration и completion
  • CAAnimation апстрактна основна класа од које наслеђују CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup
  • Render server одвојени процес (backboardd) који интерполира кадрове анимације на GPU

Шта је Core Animation?

Core Animation је Apple-ов графички фрејмворк који се појавио у Mac OS X 10.5 Leopard (2007) и пренешен на iOS од прве верзије iPhone OS (2007). Core Animation управља композицијом, анимацијом и рендеровањем слојева (CALayer) на GPU. Сваки UIView у iOS има уграђени CALayer (view.layer) кроз који се одвија целокупно рендеровање.

Core Animation ради на принципу implicit animation: неке промене својстава CALayer се анимирају аутоматски (анимира CABasicAnimation за position, bounds, opacity, backgroundColor). Implicit-анимације подразумевано користе CATransaction са трајањем од 0.25 секунди и кривом easeInOut.

Према подацима Apple WWDC 2024, Core Animation обрађује до 120 FPS на уређајима са ProMotion, користећи Metal за GPU рендеровање. Величина типичног слоја у меморији је 4 бајта по пикселу (RGBA) + overhead ~100 бајтова по слоју. Препоручује се не више од 1000 слојева на екрану за стабилних 60 FPS.

Архитектура CALayer

CALayer основа Core Animation. Сваки CALayer садржи bitmap садржај (или референцу на GPU текстуру) и дефинише геометрију (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Слој не обрађује догађаје додира за то је задужен UIView/UIScrollView. Слојеви формирају хијерархију (layer tree) која одражава view хијерархију.

Core Animation подржава три стабла слојева: model layer tree (стварна својства), presentation layer tree(тренутни приказ током анимације) и render tree (подаци за GPU). Presentation layer се користи за читање међувредности анимације у реалном времену.

Типови CALayer

CALayer има специјализоване подкласе: CAShapeLayer (векторска графика), CAGradientLayer (градијент), CATextLayer (текст), CATiledLayer (велике слике подељене на плочице), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer је најпопуларнији за прилагођену анимацију захваљујући подршци за CGPath и анимацију strokeStart/strokeEnd.

CABasicAnimation основна анимација својстава

CABasicAnimation је подкласа CAAnimation која анимира једно својство CALayer од почетне вредности (fromValue) до крајње (toValue) или релативне промене (byValue). Анимација се додаје слоју кроз метод layer.add(animation, forKey:) и извршава се у render server-у без учешћа апликације на сваком кадру.

Кључ (keyPath) је стринг који указује на својство: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity итд. Core Animation подржава 60+ анимираних keyPath. За прилагођена својства користе се CATransaction и presentation layer.

swift
import QuartzCore

// CABasicAnimation за opacity и cornerRadius
func animateLayer() {
    let layer = CALayer()
    layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
    layer.backgroundColor = UIColor.systemBlue.cgColor
    view.layer.addSublayer(layer)

    // 1. Анимација провидности
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. Анимација заобљавања углова
    let cornerAnim = CABasicAnimation(keyPath: "cornerRadius")
    cornerAnim.fromValue = 0
    cornerAnim.toValue = 50
    cornerAnim.duration = 2.0
    cornerAnim.autoreverses = true
    cornerAnim.repeatCount = .infinity

    layer.add(fadeAnim, forKey: "fade")
    layer.add(cornerAnim, forKey: "corner")
}

// Анимација position са ease-in-out
func moveLayer(_ layer: CALayer, to point: CGPoint) {
    let anim = CABasicAnimation(keyPath: "position")
    anim.fromValue = NSValue(cgPoint: layer.position)
    anim.toValue = NSValue(cgPoint: point)
    anim.duration = 0.6
    anim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
    anim.isRemovedOnCompletion = false
    anim.fillMode = .forwards
    layer.add(anim, forKey: "move")
    layer.position = point // ажурирамо model layer
}

Важно: CABasicAnimation је привремени приказ (presentation layer). Након завршетка анимације, слој се враћа на почетне вредности model layer. За фиксирање коначног стања поставите isRemovedOnCompletion = false, fillMode = .forwards и ажурирајте model layer на коначне вредности.

CATransaction груписање анимација

CATransaction је механизам за груписање Core Animation анимација у једну трансакцију. CATransaction.begin() и CATransaction.commit() дефинишу границе трансакције. Унутар трансакције могу се поставити заједнички параметри: duration, timingFunction, completionBlock, disableActions. CATransaction је основа implicit-анимација CALayer.

Implicit animation ради када се својство CALayer мења ван блока анимације: layer.opacity = 0.5. Core Animation аутоматски креира CABasicAnimation са duration из тренутног CATransaction (подразумевано 0.25 с). За искључивање implicit-анимације користите CATransaction.setDisableActions(true).

swift
// CATransaction груписање и завршетак
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // Све промене унутар трансакције се анимирају са duration 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// Искључивање implicit-анимације
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // без анимације
    CATransaction.commit()
}

// Анимација својстава CAShapeLayer
func animateProgress(percentage: CGFloat) {
    CATransaction.begin()
    CATransaction.setAnimationDuration(0.8)
    CATransaction.setCompletionBlock {
        print("Progress updated to (percentage)%")
    }
    progressLayer.strokeEnd = percentage / 100.0
    CATransaction.commit()
}

Примери кода у Swift

Core Animation се интегрише са UIKit кроз слој UIView. Пример испод демонстрира анимацију CAShapeLayer кружну траку напретка са анимацијом дужине лука и ротацијом слоја кроз CABasicAnimation.

swift
import UIKit
import QuartzCore

class CircularProgressView: UIView {

    private let progressLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath(
            arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: bounds.width / 2 - 10,
            startAngle: -.pi / 2,
            endAngle: 3 * .pi / 2,
            clockwise: true
        )

        progressLayer.path = path.cgPath
        progressLayer.strokeColor = UIColor.systemBlue.cgColor
        progressLayer.lineWidth = 8
        progressLayer.fillColor = nil
        progressLayer.strokeEnd = 0
        progressLayer.lineCap = .round
        layer.addSublayer(progressLayer)
    }

    func setProgress(_ value: CGFloat, animated: Bool = true) {
        if animated {
            CATransaction.begin()
            CATransaction.setAnimationDuration(0.6)
            CATransaction.setAnimationTimingFunction(
                CAMediaTimingFunction(name: .easeOut)
            )
            progressLayer.strokeEnd = min(max(value, 0), 1)
            CATransaction.commit()
        } else {
            progressLayer.strokeEnd = value
        }
    }
}

CAShapeLayer анимира својство strokeEnd од 0 до 1, стварајући ефекат „пуњења" кружне траке напретка. CATransaction са трајањем 0.6 и easeOut чини анимацију глатком. layer.lineCap = .round додаје заобљене крајеве линије за уреднији изглед.

Често постављана питања

Која је разлика између Core Animation и UIView.animate?

Core Animation ради на нивоу CALayer и управља се кроз CABasicAnimation, CATransaction. UIView.animate је високонивојски омотач изнад Core Animation који аутоматски креира CABasicAnimation за својства UIView. Core Animation даје више контроле: keyPath, timingFunction, fillMode, груписање кроз CATransaction.

Шта је implicit animation у Core Animation?

Implicit animation је аутоматска анимација при промени анимираног својства CALayer ван блока анимације. На пример, layer.opacity = 0.5 креира CABasicAnimation са трајањем 0.25 с. Implicit-анимације се управљају кроз CATransaction и искључују кроз setDisableActions(true).

Како анимирати прилагођено својство CALayer?

За прилагођена својства имплементирајте action(forKey:) у CALayer и вратите CAAnimation. Или користите CALayer.display() за ручно рендеровање са анимацијом кроз CADisplayLink. За својства која подржавају CABasicAnimation, довољно је навести keyPath као стринг.

Зашто је CALayer ефикаснији од UIView за анимацију?

CALayer је лакши од UIView: нема управљаче догађајима (touches, гестови), не учествује у Auto Layout и не подржава accessibility. Типичан CALayer заузима ~100 бајтова наспрам ~300+ за UIView. Core Animation обрађује слојеве у render server-у на GPU без блокирања main thread.

Закључак

  • Core Animation Apple-ов нисконвојски фрејмворк за анимацију CALayer са рендеровањем на GPU
  • CALayer основна класа са 60+ анимираних својстава, подржава CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation анимација једног својства са fromValue/toValue, додаје се кроз layer.add(animation, forKey:)
  • CATransaction груписање анимација са заједничким duration, timingFunction, completionBlock
  • Implicit animation аутоматска анимација при промени својстава CALayer (трајање 0.25 с)
  • Presentation layer тренутно стање слоја током анимације, користи се за читање међувредности
  • Перформансе до 120 FPS на ProMotion, до 1000 слојева при 60 FPS, 4 бајта/пиксел

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође