Core Animation: fundamentos, CALayer e animação em iOS

Autor: IT Sectr Publicado: 2026-03-01 Tempo de leitura: 8 min

Core Animation é o framework de animação de baixo nível da Apple que opera no nível de CALayer e renderiza conteúdo na GPU. Core Animation é a base de todas as animações em iOS e macOS: UIKit, AppKit, SceneKit e SpriteKit são construídos sobre ele. Este artigo explica a arquitetura do CALayer, CABasicAnimation, CATransaction e técnicas práticas.

Pontos principais

  • CALayer — a classe base do Core Animation para gerenciar a exibição de conteúdo na GPU
  • CABasicAnimation — uma animação simples de uma propriedade do CALayer de fromValue até toValue
  • CATransaction — agrupamento de animações em uma única transação com duração e conclusão compartilhadas
  • CAAnimation — uma classe base abstrata da qual CABasicAnimation, CAKeyframeAnimation e CAAnimationGroup herdam
  • Render server — um processo separado (backboardd) que interpola os quadros de animação na GPU

O que é Core Animation?

Core Animation é o framework gráfico da Apple introduzido no Mac OS X 10.5 Leopard (2007) e portado para iOS com a primeira versão do iPhone OS (2007). O Core Animation gerencia a composição, animação e renderização de camadas (CALayer) na GPU. Cada UIView no iOS tem um CALayer embutido (view.layer) através do qual todo o desenho ocorre.

O Core Animation opera no princípio de animação implícita: algumas alterações de propriedades do CALayer animam automaticamente (CABasicAnimation para position, bounds, opacity, backgroundColor). As animações implícitas usam CATransaction por padrão com duração de 0,25 segundos e curva easeInOut.

De acordo com a Apple WWDC 2024, o Core Animation processa até 120 FPS em dispositivos ProMotion, usando Metal para renderização em GPU. O consumo de memória de uma camada típica é de 4 bytes por pixel (RGBA) + ~100 bytes de overhead por camada. Recomenda-se não mais de 1000 camadas na tela para 60 FPS estáveis.

Arquitetura do CALayer

CALayer é a base do Core Animation. Cada CALayer contém conteúdo bitmap (ou referência de textura GPU) e define a geometria (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). As camadas não lidam com eventos de toque — UIView/UIScrollView cuidam disso. As camadas formam uma hierarquia (layer tree) que espelha a hierarquia de views.

O Core Animation mantém três árvores de camadas: a model layer tree (propriedades reais), a presentation layer tree (exibição atual durante a animação) e a render tree (dados da GPU). A camada de apresentação é usada para ler valores intermediários de animação em tempo real.

Tipos de CALayer

CALayer possui subclasses especializadas: CAShapeLayer (gráficos vetoriais), CAGradientLayer (gradiente), CATextLayer (texto), CATiledLayer (imagens grandes divididas em tiles), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer é o mais popular para animação personalizada graças ao suporte a CGPath e animação strokeStart/strokeEnd.

CABasicAnimation — animação básica de propriedades

CABasicAnimation é uma subclasse de CAAnimation que anima uma única propriedade do CALayer de um valor inicial (fromValue) até um valor final (toValue) ou por uma alteração relativa (byValue). A animação é adicionada à camada através de layer.add(animation, forKey:) e executada no render server sem envolvimento do aplicativo em cada quadro.

A chave (keyPath) é uma string que especifica a propriedade: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity, etc. O Core Animation suporta mais de 60 keyPaths animáveis. Para propriedades personalizadas, são usados CATransaction e a camada de apresentação.

swift
import QuartzCore

// CABasicAnimation para opacity e 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. Animação de opacidade
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. Animação de raio de canto
    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")
}

// Animação de position com 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 // atualizando model layer
}

Importante: CABasicAnimation é uma exibição temporária (presentation layer). Após a animação ser concluída, a camada retorna aos seus valores do model layer. Para congelar o estado final, defina isRemovedOnCompletion = false, fillMode = .forwards e atualize o model layer para os valores finais.

CATransaction — agrupamento de animações

CATransaction é um mecanismo para agrupar animações do Core Animation em uma única transação. CATransaction.begin() e CATransaction.commit() definem os limites da transação. Dentro de uma transação, parâmetros compartilhados podem ser definidos: duration, timingFunction, completionBlock, disableActions. CATransaction é a base das animações implícitas do CALayer.

A animação implícita ocorre quando uma propriedade do CALayer é alterada fora de um bloco de animação: layer.opacity = 0,5. O Core Animation cria automaticamente uma CABasicAnimation com a duração do CATransaction atual (padrão 0,25 s). Para desativar a animação implícita, use CATransaction.setDisableActions(true).

swift
// CATransaction — agrupamento e conclusão
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // Todas as alterações dentro da transação são animadas com duração 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// Desativando animação implícita
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // sem animação
    CATransaction.commit()
}

// Animando propriedades do 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()
}

Exemplos de código Swift

O Core Animation integra-se com UIKit através da camada UIView. O exemplo abaixo demonstra a animação CAShapeLayer — um progresso circular com animação de comprimento de arco e rotação da camada via 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 anima a propriedade strokeEnd de 0 a 1, criando um efeito de “preenchimento” de progresso circular. CATransaction com duração 0,6 e easeOut torna a animação suave. layer.lineCap = .round adiciona extremidades arredondadas à linha para um visual mais limpo.

Perguntas frequentes

Qual é a diferença entre Core Animation e UIView.animate?

Core Animation funciona no nível do CALayer e é controlado através de CABasicAnimation e CATransaction. UIView.animate é um wrapper de alto nível em torno do Core Animation que cria automaticamente CABasicAnimation para propriedades UIView. O Core Animation oferece mais controle: keyPath, timingFunction, fillMode, agrupamento via CATransaction.

O que é animação implícita no Core Animation?

Animação implícita é uma animação automática que ocorre quando uma propriedade animável do CALayer é alterada fora de um bloco de animação. Por exemplo, layer.opacity = 0,5 cria uma CABasicAnimation com duração de 0,25 s. As animações implícitas são gerenciadas via CATransaction e podem ser desativadas usando setDisableActions(true).

Como animar uma propriedade personalizada do CALayer?

Para propriedades personalizadas, implemente action(forKey:) no CALayer e retorne uma CAAnimation. Alternativamente, use CALayer.display() para desenho manual com animação via CADisplayLink. Para propriedades que suportam CABasicAnimation, basta especificar o keyPath como uma string.

Por que o CALayer é mais eficiente que UIView para animação?

CALayer é mais leve que UIView: não possui manipuladores de eventos (touches, gestures), não participa do Auto Layout e não suporta acessibilidade. Um CALayer típico ocupa ~100 bytes contra ~300+ do UIView. O Core Animation processa as camadas no render server na GPU sem bloquear a thread principal.

Resumo

  • Core Animation — framework de baixo nível da Apple para animação CALayer com renderização em GPU
  • CALayer — classe base com 60+ propriedades animáveis, suporta CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation — animação de única propriedade com fromValue/toValue, adicionada via layer.add(animation, forKey:)
  • CATransaction — agrupamento de animações com duration, timingFunction, completionBlock compartilhados
  • Animação implícita — animação automática ao alterar propriedades do CALayer (duração 0,25 s)
  • Presentation layer — estado atual da camada durante a animação, usado para ler valores intermediários
  • Desempenho — até 120 FPS no ProMotion, até 1000 camadas a 60 FPS, 4 bytes/pixel

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também