Core Animation: الأساسيات، CALayer والحركة في iOS

المؤلف: IT Sectr نُشر: 2026-03-01 وقت القراءة: 8 دق

Core Animation هو إطار الحركة منخفض المستوى من Apple يعمل على مستوى CALayer ويقوم بتجسيد المحتوى على وحدة معالجة الرسومات. Core Animation هو أساس جميع الحركات في iOS و macOS: UIKit، AppKit، SceneKit و SpriteKit مبنية فوقه. تشرح هذه المقالة معمارية CALayer، CABasicAnimation، CATransaction والتقنيات العملية.

النقاط الرئيسية

  • CALayer — الفئة الأساسية لـ Core Animation لإدارة عرض المحتوى على وحدة معالجة الرسومات
  • CABasicAnimation — حركة بسيطة لخاصية واحدة من CALayer من fromValue إلى toValue
  • CATransaction — تجميع الحركات في صفقة واحدة بمدة وإكمال مشتركين
  • CAAnimation — فئة أساسية مجردة يرث منها CABasicAnimation، CAKeyframeAnimation و CAAnimationGroup
  • Render server — عملية منفصلة (backboardd) تقوم بتدريج أطر الحركة على وحدة معالجة الرسومات

ما هو Core Animation؟

Core Animation هو إطار الرسومات من Apple الذي ظهر في Mac OS X 10.5 Leopard (2007) ونُقل إلى iOS مع الإصدار الأول من iPhone OS (2007). يدير Core Animation التركيب والحركة وتجسيد الطبقات (CALayer) على وحدة معالجة الرسومات. كل UIView في iOS يحتوي على CALayer مدمج (view.layer) من خلاله يتم كل الرسم.

يعمل Core Animation على مبدأ الحركة الضمنية: بعض تغييرات خصائص CALayer تتحرك تلقائياً (CABasicAnimation لـ position، bounds، opacity، backgroundColor). تستخدم الحركات الضمنية CATransaction افتراضياً بمدة 0.25 ثانية ومنحنى easeInOut.

وفقاً لـ Apple WWDC 2024، يعالج Core Animation ما يصل إلى 120 إطاراً في الثانية على أجهزة ProMotion، باستخدام Metal لتجسيد GPU. حجم الطبقة النموذجية في الذاكرة هو 4 بايت لكل بكسل (RGBA) + ~100 بايت overhead لكل طبقة. يُوصى بعدم تجاوز 1000 طبقة على الشاشة لتحقيق 60 إطاراً في الثانية مستقرة.

هندسة CALayer

CALayer هو أساس Core Animation. كل CALayer يحتوي على محتوى نقطي (أو مرجع نسيج GPU) ويحدد الهندسة (bounds، position، anchorPoint، transform، cornerRadius، borderWidth، shadow). لا تعالج الطبقات أحداث اللمس — UIView/UIScrollView هي المسؤولة عن ذلك. تشكل الطبقات تسلسلاً هرمياً (layer tree) يعكس التسلسل الهرمي للعرض.

يدعم Core Animation ثلاثة أشجار طبقات: model layer tree (الخصائص الفعلية)، presentation layer tree (العرض الحالي أثناء الحركة) و render tree (بيانات GPU). تُستخدم طبقة العرض لقراءة قيم الحركة الوسيطة في الوقت الفعلي.

أنواع 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:) وتُنفذ في خادم التجسيد دون مشاركة التطبيق في كل إطار.

المفتاح (keyPath) هو سلسلة تحدد الخاصية: opacity، position، bounds، transform.rotation.z، cornerRadius، shadowOpacity، إلخ. يدعم Core Animation أكثر من 60 keyPath قابلة للحركة. للخصائص المخصصة، يُستخدم CATransaction وطبقة العرض.

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 هي أساس الحركات الضمنية لـ CALayer.

تحدث الحركة الضمنية عندما تتغير خاصية CALayer خارج كتلة الحركة: layer.opacity = 0.5. ينشئ Core Animation تلقائياً CABasicAnimation بمدة من CATransaction الحالي (افتراضياً 0.25 ثانية). لتعطيل الحركة الضمنية، استخدم CATransaction.setDisableActions(true).

swift
// CATransaction — التجميع والإكمال
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // جميع التغييرات داخل الصفقة تتحرك بمدة 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// تعطيل الحركة الضمنية
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.

ما هي الحركة الضمنية في Core Animation؟

الحركة الضمنية هي حركة تلقائية تحدث عند تغيير خاصية قابلة للحركة من CALayer خارج كتلة الحركة. على سبيل المثال، layer.opacity = 0.5 ينشئ CABasicAnimation بمدة 0.25 ثانية. تُدار الحركات الضمنية عبر CATransaction ويمكن تعطيلها باستخدام setDisableActions(true).

كيفية تحريك خاصية مخصصة من CALayer؟

للخصائص المخصصة، قم بتنفيذ action(forKey:) في CALayer وأعد CAAnimation. بدلاً من ذلك، استخدم CALayer.display() للرسم اليدوي مع الحركة عبر CADisplayLink. للخصائص التي تدعم CABasicAnimation، يكفي تحديد keyPath كسلسلة نصية.

لماذا CALayer أكثر كفاءة من UIView للحركة؟

CALayer أخف من UIView: ليس لديه معالجات أحداث (touches، gestures)، لا يشارك في Auto Layout ولا يدعم إمكانية الوصول. CALayer نموذجي يشغل ~100 بايت مقابل ~300+ لـ UIView. يعالج Core Animation الطبقات في خادم التجسيد على GPU دون حظر الخيط الرئيسي.

الخلاصة

  • Core Animation — إطار منخفض المستوى من Apple لحركة CALayer مع تجسيد على GPU
  • CALayer — فئة أساسية مع أكثر من 60 خاصية قابلة للحركة، تدعم CAShapeLayer، CAGradientLayer، CATextLayer
  • CABasicAnimation — حركة خاصية واحدة مع fromValue/toValue، تُضاف عبر layer.add(animation, forKey:)
  • CATransaction — تجميع الحركات بمدة و timingFunction و completionBlock مشتركة
  • الحركة الضمنية — حركة تلقائية عند تغيير خصائص CALayer (مدة 0.25 ثانية)
  • طبقة العرض — حالة الطبقة الحالية أثناء الحركة، تُستخدم لقراءة القيم الوسيطة
  • الأداء — حتى 120 إطاراً في الثانية على ProMotion، حتى 1000 طبقة عند 60 إطاراً في الثانية، 4 بايت/بكسل

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا