لماذا يبطئ Swift؟ نفهم الأداء
\n\nهل سبق لك أن شغّلت تطبيق Swift الخاص بك وشعرت أنه يعمل... مثل الحلزون في ساعة الذروة؟ الشاشة تتجمد، والرسوم المتحركة تتقطع، والمستخدمون مستعدون لوضع تقييم 1 نجم في App Store. ألم مألوف؟ مرحباً بك في النادي!
\n\nSwift لغة سريعة. لقد وعدت Apple بذلك، وفي 90% من الحالات هذا صحيح. لكن هناك فارق بسيط: حتى أقوى لغة يمكن "خنقها" بمعمارية سيئة، أو تسربات ذاكرة، أو خوارزميات غير فعالة. في هذه المقالة، لن نلقي محاضرات مملة. بدلاً من ذلك، سأعرض لك أدوات وتقنيات حقيقية ستحول تطبيقك من سلحفاة إلى فهد.
\n\nهل أنت مستعد؟ لننطلق!
\n\nأدوات تحليل الأداء: أشعة إكس للكود الخاص بك
\n\nقبل تحسين أي شيء، عليك فهم ما الذي يبطئ بالضبط. التخمين على القهوة استراتيجية سيئة. هنا يأتي دور تحليل أداء كود Swift.
\n\nXcode Instruments - صديقك الرئيسي
\n\nفي Xcode هناك مجموعة أدوات مدمجة - Instruments. إنها مثل التصوير بالرنين المغناطيسي لتطبيقك: تظهر كل حركة، كل استدعاء دالة، وكل بايت من الذاكرة. يتم تشغيلها ببساطة: Product > Profile (أو Cmd + I).
إليك ثلاثة من أكثر القوالب فائدة:
\n\n- \n
- Time Profiler - يظهر أي الدوال تستهلك معظم وقت المعالج. \n
- Allocations - يتتبع تخصيص وتحرير الذاكرة. \n
- Leaks - يكتشف تسربات الذاكرة (نعم، تحدث أيضاً في Swift!). \n
مثال: تشغيل Time Profiler، تقوم بالتمرير في جدول - وترى أن 70% من الوقت يذهب إلى tableView(_:cellForRowAt:). هذه إشارة: حان وقت تحسين الخلايا.
Signposts و os_log: تحليل الأداء بدون Instruments
\n\nInstruments أداة قوية، لكنها ليست دائماً في متناول اليد. أحياناً تحتاج لقياس الأداء بسرعة مباشرة في الكود. هنا تساعد Signposts (iOS 12+):
\n\nimport os.signpost\n\nlet log = OSLog(subsystem: "com.yourapp.networking", category: .pointsOfInterest)\nlet signpostID = OSSignpostID(log: log)\n\nos_signpost(.begin, log: log, name: "fetchData", signpostID: signpostID)\n// كود تحميل البيانات الخاص بك\nos_signpost(.end, log: log, name: "fetchData", signpostID: signpostID)\n\n\nثم تفتح Instruments، تختار os_signpost - وترى الطوابع الزمنية. جميل، أليس كذلك؟
\n\nتحسين كود Swift: من البسيط إلى المعقد
\n\nالآن بعد أن عرفنا أماكن الاختناقات، دعنا نصلحها. قسمت النصائح إلى ثلاثة مستويات: للمبتدئين، وللمتقدمين، وللمحترفين.
\n\n1. المستوى الأساسي: ما يمكن للجميع فعله
\n\nلنبدأ بالواضح، لكن المنسي غالباً.
\n\nاستخدم أنواع القيم (struct) بدلاً من أنواع المراجع (class)
\n\nهذا كلاسيكي في Swift. Struct يُخزّن في المكدس، class في الكومة. المكدس سريع، الكومة بطيئة (تحتاج لتخصيص ذاكرة، عد المراجع). إذا كان كائنك صغيراً ولا يحتاج إلى وراثة - اجعله بنية (struct) بثقة.
// سيء (class)\nclass User {\n var name: String\n var age: Int\n init(name: String, age: Int) {\n self.name = name\n self.age = age\n }\n}\n\n// جيد (struct)\nstruct User {\n var name: String\n var age: Int\n}\n\n\nالتهيئة الكسولة (lazy)
\n\nلماذا تنشئ كائناً إذا قد لا تحتاجه؟ استخدم lazy var:
class DataManager {\n lazy var networkService = NetworkService() // سيتم إنشاؤه فقط عند أول استخدام\n}\n\n\nتجنب النسخ غير الضرورية
\n\nفي كل مرة تمرر فيها مصفوفة إلى دالة، قد ينسخها Swift (إذا كانت Array - نوع قيمة). استخدم inout أو UnsafeMutablePointer للبيانات الكبيرة.