مقدمة
أداء تطبيقات الهواتف المحمولة وأجهزة الكمبيوتر المكتبية هو عامل رئيسي يؤثر على تجربة المستخدم. يتوقع المستخدمون أن تعمل التطبيقات بسرعة وسلاسة وبدون تأخير. بالنسبة للمطورين الذين يستخدمون Swift لبناء تطبيقات لنظام Apple البيئي (iOS، macOS، watchOS، tvOS)، يصبح تحسين الأداء ليس مجرد أمر مرغوب فيه، بل مهمة إلزامية. في هذه المقالة، سنستعرض الطرق الرئيسية لتحسين أداء تطبيقات Swift، بدءًا من إدارة الذاكرة وصولاً إلى العمل الفعال مع تعدد المهام. ستتعلم كيفية تجنب الأخطاء الشائعة وجعل تطبيقك أسرع ما يمكن.
1. إدارة الذاكرة و ARC
يستخدم Swift آلية Automatic Reference Counting (ARC) لإدارة الذاكرة. ومع ذلك، يمكن أن يؤدي الاستخدام غير الصحيح لـ ARC إلى تسرب الذاكرة وانخفاض الأداء. المشكلة الرئيسية هي المراجع الدائرية (retain cycles).
1.1. تجنب المراجع الدائرية
تحدث المراجع الدائرية عندما يشير كائنان إلى بعضهما البعض، ولا يستطيع ARC تحرير ذاكرتهما. استخدم weak أو unowned لكسر الدائرة.
class Person { let name: String var apartment: Apartment? init(name: String) { self.name = name } deinit { print("\\(name) تم تحريره") }}
class Apartment { let unit: String weak var tenant: Person? // weak يمنع المراجع الدائرية init(unit: String) { self.unit = unit } deinit { print("الشقة \\(unit) تم تحريرها") }}
var john: Person? = Person(name: "John")var unit4A: Apartment? = Apartment(unit: "4A")john?.apartment = unit4Aunit4A?.tenant = johnjohn = nilunit4A = nil// سيتم تحرير كلا الكائنين1.2. استخدم أنواع القيم (Structs) بدلاً من أنواع المراجع (Classes)
يتم تخزين الهياكل (structs) في المكدس (stack)، وهو أسرع من التخزين في الكومة (heap) للفئات. استخدم الهياكل للبيانات الصغيرة غير القابلة للتغيير.
struct Point { var x: Double var y: Double}
class PointClass { var x: Double var y: Double init(x: Double, y: Double) { self.x = x self.y = y }}
// اختبار الأداءlet count = 1_000_000var start = CFAbsoluteTimeGetCurrent()var points = [Point](repeating: Point(x: 0, y: 0), count: count)for i in 0..<count { points[i].x = Double(i)}print("Structs: \\(CFAbsoluteTimeGetCurrent() - start) ثانية")
start = CFAbsoluteTimeGetCurrent()var pointClasses = [PointClass]()for i in 0..<count { let p = PointClass(x: Double(i), y: 0) pointClasses.append(p)}print("Classes: \\(CFAbsoluteTimeGetCurrent() - start) ثانية")2. تحسين العمل مع تعدد المهام (GCD)
Grand Central Dispatch (GCD) هي أداة قوية لتنفيذ المهام بشكل متوازٍ. الاستخدام غير الصحيح يمكن أن يؤدي إلى حالات تعليق (deadlocks) وانخفاض الأداء.
2.1. استخدم قوائم الانتظار الصحيحة
للمهام الخلفية، استخدم قوائم الانتظار العالمية مع جودة الخدمة (QoS):
.userInteractive— للمهام التي تتطلب استجابة فورية (مثل الرسوم المتحركة)..userInitiated— للمهام التي بدأها المستخدم (مثل تحميل البيانات)..utility— للمهام الطويلة (مثل معالجة الملفات)..background— للمهام التي لا تؤثر على واجهة المستخدم (مثل المزامنة).
DispatchQueue.global(qos: .userInitiated).async { // مهمة ثقيلة let result = performHeavyCalculation() DispatchQueue.main.async { // تحديث واجهة المستخدم على الخيط الرئيسي self.updateUI(with: result) }}2.2. تجنب حظر الخيط الرئيسي
يجب تنفيذ جميع العمليات المتعلقة بواجهة المستخدم على الخيط الرئيسي. انقل الحسابات الثقيلة والعمليات الشبكية