Core Animation är Apples lågnivåanimationsramverk som arbetar på CALayer-nivå och säkerställer rendering av innehåll på GPU. Core Animation är grunden för alla animationer i iOS och macOS: UIKit, AppKit, SceneKit och SpriteKit är byggda ovanpå det. Artikeln förklarar arkitekturen för CALayer, CABasicAnimation, CATransaction och praktiska tekniker.
Huvudpunkter
Core Animation är ett grafiskt ramverk från Apple som dök upp i Mac OS X 10.5 Leopard (2007) och portades till iOS från den första versionen av iPhone OS (2007). Core Animation hanterar komposition, animering och rendering av lager (CALayer) på GPU. Varje UIView i iOS har en inbyggd CALayer (view.layer) genom vilken all rendering sker.
Core Animation fungerar enligt principen för implicit animation: vissa ändringar av CALayer-egenskaper animeras automatiskt (animerar CABasicAnimation för position, bounds, opacity, backgroundColor). Implicit-animationer använder som standard CATransaction med en varaktighet på 0.25 sekunder och easeInOut-kurvan.
Enligt data från Apple WWDC 2024 bearbetar Core Animation upp till 120 FPS på ProMotion-enheter, med Metal för GPU-rendering. Storleken på ett typiskt lager i minnet är 4 byte per pixel (RGBA) + overhead ~100 byte per lager. Högst 1000 lager per skärm rekommenderas för stabila 60 FPS.
CALayer grunden för Core Animation. Varje CALayer innehåller bitmappsinnehåll (eller en referens till en GPU-textur) och definierar geometri (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Lagret bearbetar inte beröringshändelser det ansvarar UIView/UIScrollView för. Lager bildar en hierarki (layer tree) som speglar vyhierarkin.
Core Animation stöder tre lagerträd: model layer tree (faktiska egenskaper), presentation layer tree (aktuell visning under animation) och render tree (data för GPU). Presentation layer används för att läsa mellanliggande animationsvärden i realtid.
CALayer har specialiserade underklasser: CAShapeLayer (vektorgrafik), CAGradientLayer (gradient), CATextLayer (text), CATiledLayer (stora bilder uppdelade i brickor), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer är populärast för anpassad animering tack vare stöd för CGPath och animering av strokeStart/strokeEnd.
CABasicAnimation är en underklass till CAAnimation som animerar en CALayer-egenskap från startvärdet (fromValue) till slutvärdet (toValue) eller relativ ändring (byValue). Animationen läggs till lagret via metoden layer.add(animation, forKey:) och utförs i render server utan appens deltagande på varje bildruta.
Nyckeln (keyPath) är en sträng som pekar på egenskapen: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity etc. Core Animation stöder 60+ animerbara keyPath. För anpassade egenskaper används CATransaction och presentation layer.
import QuartzCore
// CABasicAnimation för opacity och 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. Animering av genomskinlighet
let fadeAnim = CABasicAnimation(keyPath: "opacity")
fadeAnim.fromValue = 1.0
fadeAnim.toValue = 0.2
fadeAnim.duration = 2.0
fadeAnim.autoreverses = true
fadeAnim.repeatCount = .infinity
// 2. Animering av avrundning av hörn
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")
}
// Animering av position med 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 // uppdaterar model layer
}Viktigt: CABasicAnimation är en tillfällig visning (presentation layer). Efter animationens slut återgår lagret till model layers ursprungliga värden. För att fixera slutläget, ställ in isRemovedOnCompletion = false, fillMode = .forwards och uppdatera model layer till slutvärdena.
CATransaction är en mekanism för att gruppera Core Animation-animationer i en enda transaktion. CATransaction.begin() och CATransaction.commit() definierar transaktionens gränser. Inuti transaktionen kan gemensamma parametrar ställas in: duration, timingFunction, completionBlock, disableActions. CATransaction är grunden för CALayers implicit-animationer.
Implicit animation fungerar när en CALayer-egenskap ändras utanför animationsblocket: layer.opacity = 0.5. Core Animation skapar automatiskt CABasicAnimation med duration från aktuell CATransaction (standard 0.25 s). För att inaktivera implicit-animation, använd CATransaction.setDisableActions(true).
// CATransaction gruppering och slutförande
func groupedAnimation() {
CATransaction.begin()
CATransaction.setAnimationDuration(1.5)
CATransaction.setAnimationTimingFunction(
CAMediaTimingFunction(name: .easeOut)
)
CATransaction.setCompletionBlock {
print("All animations completed")
}
// Alla ändringar inom transaktionen animeras med duration 1.5
layer1.opacity = 0.3
layer2.position = CGPoint(x: 200, y: 300)
layer3.backgroundColor = UIColor.systemRed.cgColor
CATransaction.commit()
}
// Inaktivering av implicit-animation
func updateWithoutAnimation() {
CATransaction.begin()
CATransaction.setDisableActions(true)
layer.frame = newFrame // utan animering
CATransaction.commit()
}
// Animering av CAShapeLayer-egenskaper
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 integreras med UIKit genom UIView-lagret. Exemplet nedan visar animering av CAShapeLayer en cirkulär förloppsindikator med animering av båglängd och rotation av lagret via 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 animerar egenskapen strokeEnd från 0 till 1, vilket skapar effekten av att “fylla” den cirkulära förloppsindikatorn. CATransaction med varaktighet 0.6 och easeOut gör animationen mjuk. layer.lineCap = .round lägger till rundade linjeändar för ett snyggare utseende.
Vanliga frågor
Core Animation arbetar på CALayer-nivå och hanteras via CABasicAnimation, CATransaction. UIView.animate är ett högnivåomslag över Core Animation som automatiskt skapar CABasicAnimation för UIView-egenskaper. Core Animation ger mer kontroll: keyPath, timingFunction, fillMode, gruppering via CATransaction.
Implicit animation är automatisk animering när en animerbar CALayer-egenskap ändras utanför animationsblocket. Till exempel skapar layer.opacity = 0.5 CABasicAnimation med varaktighet 0.25 s. Implicit-animationer hanteras via CATransaction och inaktiveras via setDisableActions(true).
För anpassade egenskaper, implementera action(forKey:) i CALayer och returnera CAAnimation. Eller använd CALayer.display() för manuell rendering med animering via CADisplayLink. För egenskaper som stöder CABasicAnimation räcker det att ange keyPath som en sträng.
CALayer är lättare än UIView: har inga händelsehanterare (touches, gester), deltar inte i Auto Layout och stöder inte accessibility. En typisk CALayer tar ~100 byte jämfört med ~300+ för UIView. Core Animation bearbetar lager i render server på GPU utan att blockera main thread.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också