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 byte ανά pixel (RGBA) + επιβάρυνση ~100 byte ανά επίπεδο. Συνιστώνται όχι περισσότερα από 1000 επίπεδα ανά οθόνη για σταθερά 60 FPS.

Αρχιτεκτονική CALayer

CALayer η βάση του Core Animation. Κάθε CALayer περιέχει bitmap περιεχόμενο (ή αναφορά σε υφή GPU) και ορίζει τη γεωμετρία (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Το επίπεδο δεν επεξεργάζεται γεγονότα αφής γι' αυτό είναι υπεύθυνο το UIView/UIScrollView. Τα επίπεδα σχηματίζουν μια ιεραρχία (layer tree) που αντικατοπτρίζει την ιεραρχία προβολής.

Το 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 byte έναντι ~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 byte/pixel

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης