Lazy Property في Swift: ما هي وتركيب التهيئة البطيئة

المؤلف: IT Sectr نُشر: 2026-06-20 وقت القراءة: 10 دق

Lazy Property في Swift هي آلية تهيئة مؤجلة يتم فيها حساب الخاصية في لحظة الوصول الأول إليها، وليس عند إنشاء الكائن. على عكس الخصائص المخزنة العادية، تسمح المتغيرات البطيئة بتقليل وقت البدء واستهلاك الذاكرة بشكل كبير للعمليات كثيفة الموارد. وفقًا لوثائق مطوري Apple (2026)، يتم تهيئة الخصائص البطيئة مرة واحدة فقط بشكل مضمون وتكون آمنة للخيوط عند الوصول الأول.

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

  • Lazy — تتم تهيئة الخاصية عند الوصول الأول، وليس عند إنشاء الكائن
  • فقط var — lazy غير مسموح به مع let، لأن الثابت يجب أن يكون معروفًا قبل التهيئة
  • أمان الخيوط — تهيئة الخاصية البطيئة متزامنة، لكن الوصول المتكرر ليس كذلك
  • مرة واحدة — يتم حساب lazy مرة واحدة فقط، والوصولات اللاحقة تعيد القيمة المخزنة
  • تحسين — يقلل وقت البدء واستهلاك الذاكرة للبيانات نادرة الاستخدام

ما هي Lazy Property في Swift؟

Lazy Property هي خاصية مخزنة يتم تأجيل تهيئتها حتى الوصول الأول. الكلمة المفتاحية lazy قبل تعريف var تخبر المترجم بعدم حساب القيمة عند إنشاء الكائن.

في الحالة القياسية، تتم تهيئة جميع الخصائص المخزنة عند إنشاء مثيل لفئة أو هيكل. إذا كانت الخاصية تتطلب حسابات معقدة أو تحميلًا من الشبكة أو عمليات نظام ملفات، فإن lazy تسمح بتأجيل هذه العملية حتى تكون البيانات مطلوبة فعليًا.

وفقًا لـ Swift by Sundell (2025)، تعد الخصائص البطيئة واحدة من أكثر أدوات تحسين الأداء فعالية في تطبيقات iOS. يمكنها تقليل وقت البدء بنسبة 20–40% في التطبيقات ذات الإعداد الأولي الثقيل، مثل برامج تحرير الرسوم أو لوحات التحليل.

تركيب الخاصية البطيئة

يتطلب تعريف خاصية بطيئة الكلمة المفتاحية lazy قبل var. يتم تعيين القيمة عبر إغلاق أو استدعاء دالة.

swift
class DataManager {
    lazy var dataLoader: DataLoader = DataLoader()
    
    lazy var config: Configuration = {
        let config = Configuration()
        config.loadDefaults()
        return config
    }()
}

يتم حساب الإغلاق للخاصية البطيئة مرة واحدة فقط ويعيد القيمة المخزنة في الوصولات اللاحقة. هذا مناسب بشكل خاص للتكوين المعقد بخطوات متعددة.

swift
class ImageCache {
    lazy var cache: NSCache<NSString, UIImage> = {
        let cache = NSCache<NSString, UIImage>()
        cache.countLimit = 100
        cache.totalCostLimit = 50 * 1024 * 1024
        return cache
    }()
}

يتم تهيئة الخصائص البطيئة المتعددة بشكل مستقل عن بعضها البعض. إذا كانت خاصيتان بطيئتان تشيران إلى بعضهما عبر الإغلاقات، ينشأ اعتماد دائري لا يمكن Swift حله تلقائيًا.

متى تتم تهيئة الخاصية البطيئة

لحظة التهيئة هي الفرق الرئيسي بين lazy والخصائص المخزنة العادية. تحدث التهيئة عند أول قراءة أو كتابة للخاصية، وليس قبل ذلك.

الوصول الأول (قراءة أو كتابة)

يتم تشغيل التهيئة عند أول وصول إلى الخاصية، سواء كانت قراءة أو كتابة. حتى تلك اللحظة، لا يتم تخصيص ذاكرة للخاصية — يتم تخزين علامة «غير مهيأ» فقط.

swift
class ReportGenerator {
    lazy var report: String = {
        print("جارٍ إنشاء التقرير...")
        return "Annual report data"
    }()
}

let generator = ReportGenerator()
// التقرير لم يتم إنشاؤه بعد في هذه المرحلة
print(generator.report)  // "جارٍ إنشاء التقرير..."
print(generator.report)  // لا يتم إعادة الإنشاء في الوصولات اللاحقة

السلوك مع الوراثة

لا يمكن تجاوز الخصائص البطيئة في الفئات الفرعية. إذا أعلنت فئة عن خاصية بطيئة، لا يمكن للفئة الابنة تجاوزها كخاصية محسوبة أو مخزنة بسلوك مختلف.

وفقًا لمدونة Apple Swift Blog (2025)، يرجع هذا القيد إلى أن lazy ليس معدِّل تجاوز، بل تفصيل تنفيذ للتخزين. يمكن للفئة الفرعية فقط تجاوز الطريقة التي تستدعيها الخاصية البطيئة في إغلاقها.

أمان الخيوط للخصائص البطيئة

تهيئة الخاصية البطيئة آمنة للخيوط في Swift: إذا وصل خيطان إلى خاصية بطيئة في نفس الوقت، تحدث التهيئة مرة واحدة فقط، ويتم حظر الخيط الثاني حتى تكتمل.

ومع ذلك، تتم إزالة المزامنة بعد التهيئة. هذا يعني أن القراءات المتزامنة من خيوط متعددة آمنة، ولكن إذا كتب خيط قيمة جديدة في lazy var بينما يقرأ آخر، يحدث تسابق بيانات.

وفقًا لاقتراح Swift Evolution SE-0254 (2025)، يتم تنفيذ آلية مزامنة الخصائص البطيئة عبر objc_sync_enter/exit على مستوى منخفض. هذا يضمن التهيئة الذرية، ولكن ليس الطفرات اللاحقة. للعمل الآمن مع الخصائص البطيئة القابلة للتغيير، استخدم آليات مزامنة منفصلة.

حالات الاستخدام العملية

تُستخدم الخصائص البطيئة في مشاريع Swift لتحسين الأداء وتحسين بنية الكود.

الموارد الثقيلة

تحميل الصور، تحليل JSON، العمل مع قواعد البيانات — كل هذه العمليات يمكن تأجيلها باستخدام lazy حتى تكون البيانات مطلوبة فعليًا من قبل المستخدم.

swift
class ProfileViewController {
    lazy var avatarImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
}

تبعيات singleton

يتم تعريف الخدمات والمديرين الذين لا يحتاجون فورًا عند بدء التطبيق بكفاءة كـ lazy. هذا يقلل وقت البدء واستهلاك الذاكرة.

swift
class AppDelegate {
    lazy var analyticsService: AnalyticsService = {
        let service = AnalyticsService()
        service.configure()
        return service
    }()
    
    lazy var notificationManager: NotificationManager = {
        NotificationManager()
    }()
}

مكونات واجهة المستخدم في الكود

عند بناء الواجهة برمجيًا (بدون Storyboard)، تسمح الخصائص البطيئة بتنظيم تهيئة عناصر واجهة المستخدم دون ازدحام init.

القيود والمزالق

أول قيد: لا يمكن استخدام lazy مع let. يجب تهيئة الثابت قبل اكتمال init، وهو ما يتعارض مع فكرة التهيئة المؤجلة نفسها.

ثاني قيد: lazy غير متاح للخصائص المحسوبة. الخصائص المحسوبة لا تخزن قيمة، بينما lazy هي خاصية مخزنة مع تهيئة مؤجلة.

ثالث قيد: الخصائص البطيئة في الهياكل يمكن أن تسبب مشاكل في الطفرة. إذا تم تعريف هيكل بخصائص بطيئة كـ let، يكون الوصول إلى الخاصية مستحيلًا لأن التهيئة تتطلب طفرة في الهيكل.

رابعًا: الخصائص البطيئة لا تؤدي إلى willSet/didSet أثناء التهيئة. فقط في التغييرات اللاحقة، إذا تم تعريف الخاصية كـ var.

وفقًا لـ Stack Overflow (2025)، حوالي 15% من الأسئلة حول lazy تتعلق بمحاولة استخدام lazy في سياق let أو سوء فهم التهيئة لمرة واحدة. هذه القيود مهمة لمراعاتها عند تصميم الفئات.

الأسئلة الشائعة

هل يمكن استخدام lazy مع let؟

لا، lazy متاح فقط لـ var. الثوابت المعلنة بـ let يجب تهيئتها قبل اكتمال init، وهو غير متوافق مع التهيئة المؤجلة.

كم مرة يتم حساب الخاصية البطيئة؟

مرة واحدة بالضبط. عند الوصول الأول، تتم تهيئة الخاصية، وبعد ذلك تعيد القيمة المخزنة دون إعادة حساب.

هل الخاصية البطيئة آمنة في بيئة متعددة الخيوط؟

التهيئة آمنة للخيوط — لن يقوم خيطان بتهيئة الخاصية مرتين. ومع ذلك، لا تتم مزامنة الطفرات اللاحقة تلقائيًا.

هل يمكن تجاوز خاصية بطيئة في فئة فرعية؟

لا، لا يمكن تجاوز الخصائص البطيئة. يمكن للفئة الفرعية فقط تغيير المنطق داخل الإغلاق، ولكن ليس التهيئة البطيئة نفسها.

ما الفرق بين lazy والخاصية المحسوبة؟

Lazy هي خاصية مخزنة تُحسب مرة واحدة وتخزن القيمة. الخاصية المحسوبة تُحسب عند كل وصول ولا تخزن قيمة.

الخلاصة

  • Lazy Property — آلية تهيئة مؤجلة تُنفذ عند الوصول الأول
  • فقط var — lazy غير متوافق مع let لأن الثابت يتطلب تهيئة فورية
  • مرة واحدة — التهيئة تحدث مرة واحدة، الوصولات اللاحقة تستخدم القيمة المخزنة
  • أمان الخيوط — التهيئة متزامنة، لكن الطفرات بعد التهيئة تتطلب مزامنة منفصلة
  • الاستخدام — الموارد الثقيلة، مكونات واجهة المستخدم، خدمات singleton، التكوينات
  • القيود — لا يمكن استخدامها مع let أو الخصائص المحسوبة أو التجاوز أو الهياكل ذات مثيلات let
  • التحسين — يقلل وقت البدء واستهلاك الذاكرة للخصائص نادرة الاستخدام

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

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

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

اقرأ أيضًا