Core Animation ist Apples Low-Level-Animation-Framework, das auf CALayer-Ebene arbeitet und Inhalte auf der GPU rendert. Core Animation ist die Grundlage aller Animationen in iOS und macOS: UIKit, AppKit, SceneKit und SpriteKit sind darauf aufgebaut. Dieser Artikel erklärt die Architektur von CALayer, CABasicAnimation, CATransaction und praktische Techniken.
Wichtige Punkte
Core Animation ist Apples Grafik-Framework, das in Mac OS X 10.5 Leopard (2007) eingeführt und mit der ersten Version von iPhone OS (2007) auf iOS portiert wurde. Core Animation verwaltet die Komposition, Animation und Darstellung von Layern (CALayer) auf der GPU. Jede UIView in iOS verfügt über einen integrierten CALayer (view.layer), über den die gesamte Zeichnung erfolgt.
Core Animation arbeitet nach dem Prinzip der impliziten Animation: Einige CALayer-Eigenschaftsänderungen animieren automatisch (CABasicAnimation für position, bounds, opacity, backgroundColor). Implizite Animationen verwenden standardmäßig CATransaction mit einer Dauer von 0,25 Sekunden und einer easeInOut-Kurve.
Laut Apple WWDC 2024 verarbeitet Core Animation bis zu 120 FPS auf ProMotion-Geräten und verwendet Metal für GPU-Rendering. Der Speicherbedarf einer typischen Ebene beträgt 4 Byte pro Pixel (RGBA) + ~100 Byte Overhead pro Ebene. Für stabile 60 FPS werden nicht mehr als 1000 Ebenen auf dem Bildschirm empfohlen.
CALayer ist die Grundlage von Core Animation. Jeder CALayer enthält Bitmap-Inhalt (oder eine GPU-Texturreferenz) und definiert die Geometrie (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Layer behandeln keine Berührungsereignisse — dafür sind UIView/UIScrollView zuständig. Layer bilden eine Hierarchie (Layer Tree), die die View-Hierarchie widerspiegelt.
Core Animation verwaltet drei Layer-Bäume: den model layer tree (tatsächliche Eigenschaften), den presentation layer tree (aktuelle Anzeige während der Animation) und den render tree (GPU-Daten). Die Presentation Layer wird zum Auslesen von Echtzeit-Zwischenanimationswerten verwendet.
CALayer verfügt über spezialisierte Unterklassen: CAShapeLayer (Vektorgrafiken), CAGradientLayer (Farbverlauf), CATextLayer (Text), CATiledLayer (große Bilder, aufgeteilt in Kacheln), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer ist dank CGPath-Unterstützung und strokeStart/strokeEnd-Animation am beliebtesten für benutzerdefinierte Animationen.
CABasicAnimation ist eine Unterklasse von CAAnimation, die eine einzelne CALayer-Eigenschaft von einem Startwert (fromValue) bis zu einem Endwert (toValue) oder durch eine relative Änderung (byValue) animiert. Die Animation wird der Ebene über layer.add(animation, forKey:) hinzugefügt und läuft im Render-Server ohne Beteiligung der App an jedem Frame.
Der Schlüssel (keyPath) ist ein String, der die Eigenschaft angibt: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity usw. Core Animation unterstützt über 60 animierbare keyPaths. Für benutzerdefinierte Eigenschaften werden CATransaction und die Presentation Layer verwendet.
import QuartzCore
// CABasicAnimation für opacity und 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. Deckkraft-Animation
let fadeAnim = CABasicAnimation(keyPath: "opacity")
fadeAnim.fromValue = 1.0
fadeAnim.toValue = 0.2
fadeAnim.duration = 2.0
fadeAnim.autoreverses = true
fadeAnim.repeatCount = .infinity
// 2. Eckenradius-Animation
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-Animation mit 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 aktualisieren
}Wichtig: CABasicAnimation ist eine temporäre Anzeige (presentation layer). Nach Abschluss der Animation kehrt der Layer zu seinen model layer-Werten zurück. Um den Endzustand einzufrieren, setzen Sie isRemovedOnCompletion = false, fillMode = .forwards und aktualisieren Sie den model layer auf die Endwerte.
CATransaction ist ein Mechanismus zum Gruppieren von Core Animation-Animationen in einer einzigen Transaktion. CATransaction.begin() und CATransaction.commit() definieren die Transaktionsgrenzen. Innerhalb einer Transaktion können gemeinsame Parameter festgelegt werden: duration, timingFunction, completionBlock, disableActions. CATransaction ist die Grundlage der impliziten CALayer-Animationen.
Implizite Animation tritt auf, wenn eine CALayer-Eigenschaft außerhalb eines Animationsblocks geändert wird: layer.opacity = 0,5. Core Animation erstellt automatisch eine CABasicAnimation mit der Dauer der aktuellen CATransaction (standardmäßig 0,25 s). Um die implizite Animation zu deaktivieren, verwenden Sie CATransaction.setDisableActions(true).
// CATransaction — Gruppierung und Fertigstellung
func groupedAnimation() {
CATransaction.begin()
CATransaction.setAnimationDuration(1.5)
CATransaction.setAnimationTimingFunction(
CAMediaTimingFunction(name: .easeOut)
)
CATransaction.setCompletionBlock {
print("All animations completed")
}
// Alle Änderungen innerhalb der Transaktion werden mit Dauer 1.5 animiert
layer1.opacity = 0.3
layer2.position = CGPoint(x: 200, y: 300)
layer3.backgroundColor = UIColor.systemRed.cgColor
CATransaction.commit()
}
// Implizite Animation deaktivieren
func updateWithoutAnimation() {
CATransaction.begin()
CATransaction.setDisableActions(true)
layer.frame = newFrame // ohne Animation
CATransaction.commit()
}
// CAShapeLayer-Eigenschaften animieren
func animateProgress(percentage: CGFloat) {
CATransaction.begin()
CATransaction.setAnimationDuration(0.8)
CATransaction.setCompletionBlock {
print("Progress updated to (percentage)%")
}
progressLayer.strokeEnd = percentage / 100.0
CATransaction.commit()
}Core Animation integriert sich über die UIView-Ebene in UIKit. Das folgende Beispiel zeigt eine CAShapeLayer-Animation — einen kreisförmigen Fortschritt mit Bogenlängenanimation und Layer-Rotation über CABasicAnimation.
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 animiert die Eigenschaft strokeEnd von 0 bis 1 und erzeugt so einen „Füll“-Effekt des kreisförmigen Fortschritts. CATransaction mit einer Dauer von 0,6 und easeOut macht die Animation flüssig. layer.lineCap = .round fügt abgerundete Linienenden für ein saubereres Erscheinungsbild hinzu.
Häufig gestellte Fragen
Core Animation arbeitet auf CALayer-Ebene und wird über CABasicAnimation und CATransaction gesteuert. UIView.animate ist ein High-Level-Wrapper um Core Animation, der automatisch CABasicAnimation für UIView-Eigenschaften erstellt. Core Animation bietet mehr Kontrolle: keyPath, timingFunction, fillMode, Gruppierung über CATransaction.
Implizite Animation ist eine automatische Animation, die auftritt, wenn eine animierbare CALayer-Eigenschaft außerhalb eines Animationsblocks geändert wird. Zum Beispiel erstellt layer.opacity = 0,5 eine CABasicAnimation mit 0,25 s Dauer. Implizite Animationen werden über CATransaction verwaltet und können mit setDisableActions(true) deaktiviert werden.
Für benutzerdefinierte Eigenschaften implementieren Sie action(forKey:) in CALayer und geben eine CAAnimation zurück. Alternativ verwenden Sie CALayer.display() für manuelles Zeichnen mit Animation über CADisplayLink. Für Eigenschaften, die CABasicAnimation unterstützen, geben Sie einfach den keyPath als String an.
CALayer ist leichter als UIView: Es hat keine Event-Handler (touches, gestures), nimmt nicht an Auto Layout teil und unterstützt keine Barrierefreiheit. Ein typischer CALayer benötigt ~100 Bytes gegenüber ~300+ bei UIView. Core Animation verarbeitet Layer im Render-Server auf der GPU, ohne den Hauptthread zu blockieren.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch