حيل أداء iOS لجعل تطبيقك أكثر أداءً

نشرت: 2022-03-10
ملخص سريع ↬ يعد الأداء الجيد أمرًا بالغ الأهمية لتقديم تجربة مستخدم جيدة ، وغالبًا ما يكون لدى مستخدمي iOS توقعات عالية من تطبيقاتهم. قد يجعل التطبيق البطيء وغير المستجيب المستخدمين يتخلون عن استخدام تطبيقك ، أو الأسوأ من ذلك ، أن يتركوا تقييمًا سيئًا.

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

1. خلية قابلة لإعادة الاستخدام Dequeue

من المحتمل أنك استخدمت tableView.dequeueReusableCell(withIdentifier:for:) داخل tableView(_:cellForRowAt:) من قبل. هل تساءلت يومًا عن سبب ضرورة اتباع واجهة برمجة التطبيقات المحرجة هذه ، بدلاً من مجرد تمرير مجموعة من الخلايا فيها؟ دعنا نستعرض أسباب ذلك.

لنفترض أن لديك طريقة عرض جدول بألف صف. بدون استخدام خلايا قابلة لإعادة الاستخدام ، سيتعين علينا إنشاء خلية جديدة لكل صف ، على النحو التالي:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Create a new cell whenever cellForRowAt is called. let cell = UITableViewCell() cell.textLabel?.text = "Cell \(indexPath.row)" return cell }

كما كنت تعتقد ، سيضيف هذا ألف خلية إلى ذاكرة الجهاز أثناء التمرير إلى الأسفل. تخيل ما سيحدث إذا احتوت كل خلية على UIImageView والكثير من النص: قد يؤدي تحميلهم جميعًا مرة واحدة إلى نفاد ذاكرة التطبيق! بصرف النظر عن ذلك ، تتطلب كل خلية ذاكرة جديدة لتخصيصها أثناء التمرير. إذا قمت بالتمرير في عرض الجدول بسرعة ، فسيتم تخصيص الكثير من أجزاء الذاكرة الصغيرة أثناء التنقل ، وستجعل هذه العملية واجهة المستخدم صعبة!

لحل هذه المشكلة ، زودتنا Apple dequeueReusableCell(withIdentifier:for:) . تعمل إعادة استخدام الخلية عن طريق وضع الخلية التي لم تعد مرئية على الشاشة في قائمة انتظار ، وعندما تكون خلية جديدة على وشك الظهور على الشاشة (على سبيل المثال ، الخلية التالية أدناه أثناء قيام المستخدم بالتمرير لأسفل) ، فإن عرض الجدول سيكون استرداد خلية من قائمة الانتظار هذه وتعديلها في طريقة cellForRowAt indexPath:

آلية قائمة انتظار إعادة استخدام الخلية
كيف تعمل قوائم انتظار إعادة استخدام الخلايا في iOS (معاينة كبيرة)

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

باستخدام dequeueReusableCell ، يمكننا تقليل الذاكرة المستخدمة بواسطة التطبيق وجعلها أقل عرضة لنفاد الذاكرة!

المزيد بعد القفز! أكمل القراءة أدناه ↓

2. استخدام شاشة التشغيل التي تشبه الشاشة الأولية

كما هو مذكور في إرشادات الواجهة البشرية (HIG) من Apple ، يمكن استخدام شاشات الإطلاق لتعزيز تصور استجابة التطبيق:

"الغرض الوحيد منه هو تحسين تصور التطبيق الخاص بك على أنه سريع التشغيل وجاهز للاستخدام على الفور. يجب أن يوفر كل تطبيق شاشة تشغيل ".

من الخطأ الشائع استخدام شاشة التشغيل كشاشة البداية لإظهار العلامة التجارية أو لإضافة رسم متحرك للتحميل. صمم شاشة التشغيل لتكون مطابقة للشاشة الأولى لتطبيقك كما ذكرت آبل:

"صمم شاشة تشغيل مطابقة تقريبًا للشاشة الأولى لتطبيقك. إذا قمت بتضمين عناصر تبدو مختلفة عند انتهاء تشغيل التطبيق ، فيمكن للأشخاص تجربة وميض غير سار بين شاشة التشغيل والشاشة الأولى من التطبيق.

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

قد يؤدي استخدام شاشة التشغيل لأغراض التحميل أو العلامة التجارية إلى إبطاء وقت الاستخدام لأول مرة وجعل المستخدم يشعر أن التطبيق بطيء.

عند بدء مشروع iOS جديد ، سيتم إنشاء LaunchScreen.storyboard فارغ. ستظهر هذه الشاشة للمستخدم أثناء تحميل التطبيق لوحدات التحكم في العرض والتخطيط.

لجعل تطبيقك يشعر بشكل أسرع ، يمكنك تصميم شاشة التشغيل لتكون مشابهة للشاشة الأولى (وحدة التحكم في العرض) التي سيتم عرضها للمستخدم.

على سبيل المثال ، تشبه شاشة تشغيل تطبيق Safari طريقة العرض الأولى:

شاشة الإطلاق والعرض الأول تبدو متشابهة
مقارنة بين شاشة التشغيل والعرض الأول لتطبيق Safari (معاينة كبيرة)

تشبه لوحة عمل شاشة التشغيل أي ملف لوحة عمل آخر ، باستثناء أنه يمكنك فقط استخدام فئات UIKit القياسية ، مثل UIViewController و UITabBarController و UINavigationController. إذا حاولت استخدام أي فئات فرعية مخصصة أخرى (مثل UserViewController) ، فسوف يخطرك Xcode بأن استخدام أسماء فئة مخصصة محظور.

يظهر Xcode خطأ عند استخدام فئة مخصصة
لا يمكن أن تحتوي لوحة العمل لشاشة الإطلاق على فئة غير قياسية لـ UIKit. (معاينة كبيرة)

شيء آخر يجب ملاحظته هو أن UIActivityIndicatorView لا يتحرك عند وضعه على شاشة التشغيل ، لأن iOS سينشئ صورة ثابتة من لوحة العمل على شاشة الإطلاق ويعرضها للمستخدم. (هذا مذكور بإيجاز في العرض التقديمي WWDC 2014 "منصات حالة الاتحاد" ، حوالي 01:21:56 .)

كما تنصحنا HIG من Apple بعدم تضمين نص على شاشة التشغيل الخاصة بنا ، لأن شاشة التشغيل ثابتة ، ولا يمكنك ترجمة النص ليلائم اللغات المختلفة.

يوصى بالقراءة : تطبيق جوال مزود بميزة التعرف على الوجه: كيفية جعله حقيقيًا

3. استعادة الحالة لعرض المتحكمين

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

في شاشة تعدد المهام ، يمكننا رؤية قائمة بالتطبيقات التي تم وضعها في الخلفية. قد نفترض أن هذه التطبيقات لا تزال تعمل في الخلفية ؛ في الواقع ، قد يتم قتل بعض هذه التطبيقات وإعادة تشغيلها بواسطة النظام بسبب متطلبات الذاكرة. لقطات التطبيق التي نراها في عرض المهام المتعددة هي في الواقع لقطات شاشة مأخوذة بواسطة النظام من اليمين عندما خرجنا من التطبيق (أي للذهاب إلى الصفحة الرئيسية أو شاشة تعدد المهام).

يبتدع نظام iOS وهم التطبيقات التي تعمل في الخلفية من خلال التقاط لقطة شاشة لآخر عرض
لقطات من التطبيقات التي تم التقاطها بواسطة iOS عند خروج المستخدم من التطبيق (معاينة كبيرة)

يستخدم iOS لقطات الشاشة هذه لإعطاء الوهم بأن التطبيق لا يزال قيد التشغيل أو لا يزال يعرض هذا العرض المحدد ، في حين أن التطبيق قد يكون قد تم بالفعل إنهاءه أو إعادة تشغيله في الخلفية بينما لا يزال يعرض نفس لقطة الشاشة.

هل سبق لك أن واجهت ، عند استئناف تطبيق من شاشة تعدد المهام ، أن التطبيق يعرض واجهة مستخدم مختلفة عن اللقطة المعروضة في عرض المهام المتعددة؟ هذا لأن التطبيق لم ينفذ آلية استعادة الحالة ، وفقدت البيانات المعروضة عندما تم إيقاف التطبيق في الخلفية. يمكن أن يؤدي هذا إلى تجربة سيئة لأن المستخدم يتوقع أن يكون تطبيقك في نفس الحالة التي تركها عند مغادرته.

من مقال آبل:

"إنهم يتوقعون أن يكون تطبيقك في نفس الحالة التي كانوا عليها عندما تركوه. يضمن الحفاظ على الحالة واستعادتها عودة تطبيقك إلى حالته السابقة عند إطلاقه مرة أخرى ".

تقوم UIKit بالكثير من العمل لتبسيط عملية الحفاظ على الحالة واستعادتها بالنسبة لنا: فهي تتولى حفظ حالة التطبيق وتحميلها تلقائيًا في الأوقات المناسبة. كل ما نحتاج إلى القيام به هو إضافة بعض التهيئة لإخبار التطبيق بدعم الحفاظ على الحالة واستعادتها وإخبار التطبيق بالبيانات التي يجب حفظها.

لتمكين حفظ الحالة واستعادتها ، يمكننا تنفيذ هاتين الطريقتين في AppDelegate.swift :

 func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { return true }
 func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { return true }

سيخبر هذا التطبيق بحفظ حالة التطبيق واستعادتها تلقائيًا.

بعد ذلك ، سنخبر التطبيق عن أدوات التحكم في العرض التي يجب الاحتفاظ بها. نقوم بذلك عن طريق تحديد "معرف الاستعادة" في لوحة العمل:

تعيين معرف الاستعادة في القصة المصورة
تعيين معرف الاستعادة في لوحة العمل (معاينة كبيرة)

يمكنك أيضًا التحقق من "استخدام معرف لوحة العمل" لاستخدام معرف لوحة العمل كمعرف الاستعادة.

لتعيين معرف الاستعادة في الكود ، يمكننا استخدام خاصية restorationIdentifier لوحدة التحكم في العرض.

 // ViewController.swift self.restorationIdentifier = "MainVC"

أثناء الاحتفاظ بالحالة ، سيتم حفظ حالتها على القرص لأي وحدة تحكم في العرض أو طريقة عرض تم تخصيص معرّف استعادة لها.

يمكن تجميع معرّفات الاستعادة معًا لتشكيل مسار استعادة. يتم تجميع المعرفات باستخدام التسلسل الهرمي للعرض ، من وحدة التحكم في عرض الجذر إلى وحدة التحكم في العرض النشط الحالية. لنفترض أن MyViewController مضمن في وحدة تحكم التنقل ، المضمنة في وحدة تحكم شريط علامات تبويب أخرى. بافتراض أنهم يستخدمون أسماء الفئات الخاصة بهم كمعرفات استعادة ، سيبدو مسار الاستعادة كما يلي:

 TabBarController/NavigationController/MyViewController

عندما يغادر المستخدم التطبيق مع كون متحكم MyViewController هو وحدة تحكم العرض النشط ، سيتم حفظ هذا المسار بواسطة التطبيق ؛ ثم سيتذكر التطبيق التسلسل الهرمي للعرض السابق المعروض ( Tab Bar ControllerNavigation ControllerMy View Controller ).

بعد تعيين معرف الاستعادة ، سنحتاج إلى تنفيذ encodeRestorableState (مع المبرمج :) و decodeRestorableState (مع المبرمج :) لكل من وحدات التحكم في العرض المحفوظة. تتيح لنا هاتان الطريقتان تحديد البيانات التي يجب حفظها أو تحميلها وكيفية تشفيرها أو فك تشفيرها.

دعونا نرى وحدة التحكم في العرض:

 // MyViewController.swift​ // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { // will be called during state preservation override func encodeRestorableState(with coder: NSCoder) { // encode the data you want to save during state preservation coder.encode(self.username, forKey: "username") super.encodeRestorableState(with: coder) } // will be called during state restoration override func decodeRestorableState(with coder: NSCoder) { // decode the data saved and load it during state restoration if let restoredUsername = coder.decodeObject(forKey: "username") as? String { self.username = restoredUsername } super.decodeRestorableState(with: coder) } } // MyViewController.swift​ // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { // will be called during state preservation override func encodeRestorableState(with coder: NSCoder) { // encode the data you want to save during state preservation coder.encode(self.username, forKey: "username") super.encodeRestorableState(with: coder) } // will be called during state restoration override func decodeRestorableState(with coder: NSCoder) { // decode the data saved and load it during state restoration if let restoredUsername = coder.decodeObject(forKey: "username") as? String { self.username = restoredUsername } super.decodeRestorableState(with: coder) } }

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

بمجرد الانتهاء من فك تشفير الكائنات ، سيتم استدعاء applicationFinishedRestoringState() لإخبار وحدة التحكم في العرض باستعادة الحالة. يمكننا تحديث واجهة المستخدم لوحدة التحكم في العرض بهذه الطريقة.

 // MyViewController.swift​ // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { ... override func applicationFinishedRestoringState() { // update the UI here self.usernameLabel.text = self.username } } // MyViewController.swift​ // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { ... override func applicationFinishedRestoringState() { // update the UI here self.usernameLabel.text = self.username } }

ها أنت ذا! هذه هي الطرق الأساسية لتنفيذ المحافظة على الحالة واستعادتها لتطبيقك. ضع في اعتبارك أن نظام التشغيل سيزيل الحالة المحفوظة عندما يتم إغلاق التطبيق بالقوة من قبل المستخدم ، وذلك لتجنب الوقوع في حالة معطلة في حالة حدوث خطأ ما في الحفاظ على الحالة واستعادتها.

أيضًا ، لا تقم بتخزين أي بيانات نموذجية (أي البيانات التي كان يجب حفظها في UserDefaults أو البيانات الأساسية) في الحالة ، على الرغم من أنه قد يبدو من الملائم القيام بذلك. ستتم إزالة بيانات الحالة عندما تغادر قوة المستخدم تطبيقك ، وأنت بالتأكيد لا تريد أن تفقد بيانات النموذج بهذه الطريقة.

لاختبار ما إذا كان الحفاظ على الحالة واستعادتها يعملان بشكل جيد ، اتبع الخطوات التالية:

  1. أنشئ تطبيقًا وشغّله باستخدام Xcode.
  2. انتقل إلى الشاشة مع الحفاظ على الحالة واستعادتها التي تريد اختبارها.
  3. ارجع إلى الشاشة الرئيسية (عن طريق التمرير لأعلى أو النقر المزدوج فوق زر الصفحة الرئيسية ، أو الضغط على Shift ⇧ + Cmd ⌘ + H في المحاكي) لإرسال التطبيق إلى الخلفية.
  4. أوقف التطبيق في Xcode بالضغط على الزر.
  5. قم بتشغيل التطبيق مرة أخرى وتحقق مما إذا كانت الحالة قد تمت استعادتها بنجاح.

نظرًا لأن هذا القسم لا يغطي سوى أساسيات الحفاظ على الحالة واستعادتها ، فإنني أوصي بالمقالات التالية التي نشرتها شركة Apple Inc. لمزيد من المعرفة المتعمقة باستعادة الحالة:

  1. الحفاظ على الدولة واستعادتها
  2. عملية الحفاظ على واجهة المستخدم
  3. عملية استعادة واجهة المستخدم

4. تقليل استخدام وجهات النظر غير مبهمة بقدر الإمكان

العرض المعتم هو عرض لا يحتوي على شفافية ، مما يعني أن أي عنصر واجهة مستخدم يوضع خلفه غير مرئي على الإطلاق. يمكننا ضبط العرض ليكون معتمًا في Interface Builder:

سيؤدي هذا إلى إعلام نظام الرسم لتخطي الرسم أيًا كان وراء هذا العرض
اضبط UIView على معتم في لوحة العمل (معاينة كبيرة)

أو يمكننا القيام بذلك برمجيًا باستخدام خاصية isOpaque لـ UIView:

 view.isOpaque = true

سيؤدي تعيين العرض إلى معتم إلى جعل نظام الرسم يحسن بعض أداء الرسم أثناء عرض الشاشة.

إذا كان العرض يحتوي على شفافية (أي أن ألفا أقل من 1.0) ، فسيتعين على iOS القيام بعمل إضافي لحساب ما يجب عرضه عن طريق مزج طبقات مختلفة من طرق العرض في التسلسل الهرمي للعرض. من ناحية أخرى ، إذا تم تعيين العرض على معتم ، فسيقوم نظام الرسم فقط بوضع هذا العرض في المقدمة ويتجنب العمل الإضافي المتمثل في مزج طبقات العرض المتعددة خلفه.

يمكنك التحقق من الطبقات التي يتم مزجها (غير معتمة) في iOS Simulator عن طريق تحديد DebugColor Blended Layers .

اللون الأخضر غير ممزوج ، والأحمر عبارة عن طبقة ممزوجة
إظهار الطبقات الممزوجة بالألوان في Simulator

بعد تحديد خيار Color Blended Layers ، يمكنك أن ترى أن بعض العروض باللون الأحمر والبعض الآخر باللون الأخضر. يشير اللون الأحمر إلى أن العرض ليس معتمًا وأن عرض الإخراج الخاص به ناتج عن طبقات ممزوجة خلفه. يشير اللون الأخضر إلى أن العرض معتم ولم يتم إجراء مزج.

مع خلفية لون معتم ، لا تحتاج الطبقة إلى المزج مع طبقة أخرى
قم بتعيين لون خلفية غير شفاف لـ UILabel كلما أمكن ذلك لتقليل طبقات الألوان الممزوجة. (معاينة كبيرة)

يتم تمييز الملصقات الموضحة أعلاه ("عرض الأصدقاء" ، وما إلى ذلك) باللون الأحمر لأنه عندما يتم سحب تسمية إلى لوحة العمل ، يتم تعيين لون الخلفية الخاص بها على شفاف بشكل افتراضي. عندما يقوم نظام الرسم بتكوين الشاشة بالقرب من منطقة الملصق ، فإنه سيطلب الطبقة الموجودة خلف الملصق ويقوم ببعض العمليات الحسابية.

تتمثل إحدى الطرق التي يمكنك من خلالها تحسين أداء التطبيق في تقليل عدد المشاهدات التي يتم تمييزها باللون الأحمر قدر الإمكان.

من خلال تغيير label.backgroundColor = UIColor.clear to label.backgroundColor = UIColor.white ، يمكننا تقليل مزج الطبقة بين التسمية وطبقة العرض خلفها.

سيؤدي استخدام لون خلفية شفاف إلى مزج الطبقات
يتم تمييز العديد من الملصقات باللون الأحمر لأن لون خلفيتها شفاف ، مما يجعل نظام التشغيل iOS يحسب لون الخلفية عن طريق مزج العرض خلفه. (معاينة كبيرة)

ربما لاحظت أنه حتى إذا قمت بتعيين UIImageView على معتم وتعيين لون خلفية له ، فسيظل المحاكي يعرض اللون الأحمر في عرض الصورة. ربما يكون هذا بسبب أن الصورة التي استخدمتها لعرض الصورة لها قناة ألفا.

لإزالة قناة ألفا لصورة ما ، يمكنك استخدام تطبيق Preview لعمل نسخة مكررة من الصورة ( Shift ⇧ + Cmd ⌘ + S ) ، وإلغاء تحديد خانة الاختيار "Alpha" عند الحفظ.

قم بإلغاء تحديد خانة الاختيار "ألفا" عند حفظ صورة لتجاهل قناة ألفا.
قم بإلغاء تحديد خانة الاختيار "ألفا" عند حفظ صورة لتجاهل قناة ألفا. (معاينة كبيرة)

5. تمرير وظائف المعالجة الثقيلة إلى الخيوط الخلفية (GCD)

نظرًا لأن UIKit يعمل فقط على الخيط الرئيسي ، فإن إجراء معالجة مكثفة على الخيط الرئيسي سيؤدي إلى إبطاء واجهة المستخدم. يستخدم UIKit الخيط الرئيسي ليس فقط للتعامل مع مدخلات المستخدم والاستجابة لها ، ولكن أيضًا لرسم الشاشة.

المفتاح لجعل التطبيق مستجيبًا هو نقل أكبر عدد ممكن من مهام المعالجة الثقيلة إلى سلاسل الرسائل في الخلفية قدر الإمكان. تجنب إجراء العمليات الحسابية المعقدة ، والشبكات ، وعمليات الإدخال / الإخراج الثقيلة (مثل القراءة والكتابة على القرص) على الخيط الرئيسي.

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

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

تجنب تشغيل المهام كثيفة الأداء أو التي تستغرق وقتًا طويلاً على مؤشر الترابط الرئيسي
إليك كيفية معالجة مؤشر الترابط الرئيسي لمهام واجهة المستخدم ولماذا يتسبب في تعليق واجهة المستخدم عند تنفيذ المهام الثقيلة. (معاينة كبيرة)

بشكل افتراضي ، يتم تنفيذ التعليمات البرمجية الموجودة داخل طرق دورة حياة وحدة التحكم في العرض (مثل viewDidLoad) ووظائف IBOutlet في السلسلة الرئيسية. لنقل مهام المعالجة الثقيلة إلى سلسلة رسائل في الخلفية ، يمكننا استخدام قوائم انتظار Grand Central Dispatch التي توفرها Apple.

هذا هو قالب تبديل قوائم الانتظار:

 // Switch to background thread to perform heavy task. DispatchQueue.global(qos: .default).async { // Perform heavy task here. // Switch back to main thread to perform UI-related task. DispatchQueue.main.async { // Update UI. } }

qos تعني "جودة الخدمة". تشير قيم جودة الخدمة المختلفة إلى أولويات مختلفة للمهام المحددة. سيخصص نظام التشغيل وقتًا أكبر لوحدة المعالجة المركزية وإنتاجية إدخال / إخراج طاقة وحدة المعالجة المركزية للمهام المخصصة في قوائم الانتظار ذات قيم جودة الخدمة الأعلى ، مما يعني أن المهمة ستنتهي بشكل أسرع في قائمة انتظار ذات قيم جودة خدمة أعلى. ستستهلك قيمة جودة الخدمة الأعلى أيضًا المزيد من الطاقة نظرًا لاستخدامها المزيد من الموارد.

فيما يلي قائمة بقيم QoS من أعلى إلى أدنى أولوية:

قيم جودة الخدمة في قائمة الانتظار مرتبة حسب الأداء وكفاءة الطاقة
قيم جودة الخدمة لقائمة الانتظار مرتبة حسب الأداء وكفاءة الطاقة (معاينة كبيرة)

قدمت Apple جدولاً مفيدًا به أمثلة على قيم QoS لاستخدامها في مهام مختلفة.

شيء واحد يجب مراعاته هو أنه يجب دائمًا تنفيذ جميع أكواد UIKit على السلسلة الرئيسية. يمكن أن يؤدي تعديل كائنات UIKit (مثل UILabel و UIImageView ) على مؤشر ترابط الخلفية إلى نتيجة غير مقصودة ، مثل عدم تحديث واجهة المستخدم فعليًا ، أو حدوث عطل ، وما إلى ذلك.

من مقال آبل:

"يعد تحديث واجهة المستخدم على سلسلة محادثات بخلاف السلسلة الرئيسية خطأ شائعًا يمكن أن يؤدي إلى فقدان تحديثات واجهة المستخدم والعيوب المرئية وتلف البيانات والأعطال."

أوصي بمشاهدة فيديو WWDC 2012 من Apple حول تزامن واجهة المستخدم لفهم كيفية إنشاء تطبيق سريع الاستجابة بشكل أفضل.

ملاحظات

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

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

مزيد من الموارد

  • "A Suite of Delicious iOS Eye Candy" ، تيم أوليفر ، لقاء طوكيو iOS 2018 (فيديو)
  • "إنشاء واجهات مستخدم متزامنة على iOS" ، آندي ماتوشاك ، WWDC 2012 (فيديو)
  • "الحفاظ على واجهة مستخدم تطبيقك عبر عمليات الإطلاق" ، Apple
  • "دليل برمجة التزامن: قوائم انتظار الإرسال" ، أرشيف التوثيق ، شركة آبل
  • "مدقق الخيط الرئيسي ،" أبل