بعد Xcode 11.2: تعطل التطبيق بسبب _UITextLayoutView — الحل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

بعد تحديث Xcode 11.2 يتعطل التطبيق: كيفية التغلب على _UITextLayoutView

\n\n

هل حدث معك هذا: كنت تعمل بهدوء على مشروعك، كل شيء يعمل بسلاسة، الاختبارات تمر، المستخدمون سعداء. ثم فجأة! تقوم بتحديث Xcode إلى الإصدار 11.2، تشغل التطبيق، فيتعطل مع خطأ غامض _UITextLayoutView. هل هذا مألوف؟ إذا كان الأمر كذلك، فأنت لست وحدك. هذه المشكلة فجرت Stack Overflow حرفيًا في نهاية عام 2019 (آلاف المشاهدات في أسبوع واحد).

\n\n

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

\n\n

ما هو هذا المخلوق _UITextLayoutView؟

\n\n

لنبدأ بالنظرية. _UITextLayoutView هي فئة داخلية (خاصة) من UIKit مسؤولة عن عرض النص في UITextView. لا توثقها Apple علنًا، لذلك عندما حدث خطأ ما في Xcode 11.2 مع هذه الفئة، وجد المطورون أنفسهم في مأزق. يبدو الخطأ كالتالي تقريبًا:

\n\n
*** إنهاء التطبيق بسبب استثناء غير ممسوك 'NSInvalidArgumentException'، السبب: '-[_UITextLayoutView setFrame:]: تم إرسال محدد غير معروف إلى المثيل 0x...'
\n\n

العبارة الرئيسية هي "تم إرسال محدد غير معروف إلى المثيل". هذا يعني أنك تحاول استدعاء الأسلوب setFrame: على كائن لا يدعمه. وبما أن _UITextLayoutView هي فئة خاصة، فقد كان سلوكها مختلفًا قبل Xcode 11.2.

\n\n

من هم في مجموعة الخطر؟

\n\n

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

\n
    \n
  • أنت تستخدم UITextView مع تفعيل تغيير الحجم التلقائي (auto-sizing).
  • \n
  • لديك تسلسل هرمي مخصص للعروض، حيث يكون UITextView متداخلاً داخل UIScrollView أو UITableViewCell.
  • \n
  • أنت تتفاعل بنشاط مع حقل النص: التمرير، التحرير، تغيير الخط.
  • \n
\n\n

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

\n\n

الخطوة 1: التشخيص — ابحث عن الجاني

\n\n

قبل العلاج، دعنا نتأكد من أن المشكلة تكمن بالفعل في _UITextLayoutView. افتح وحدة تحكم Xcode (View → Debug Area → Activate Console) وقم بتشغيل التطبيق. إذا رأيت خطأ مشابهًا للذي ذكرته أعلاه، فأنت على الطريق الصحيح.

\n\n

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

\n\n

الخطوة 2: حل بسيط وسريع (للمستعجلين)

\n\n

الإصلاح الأكثر شيوعًا على Stack Overflow هو تعطيل تغيير الحجم التلقائي لـ UITextView. إليك كيفية القيام بذلك:

\n\n
// في viewDidLoad الخاص بك أو طريقة الإعداد\ntextView.isScrollEnabled = false\ntextView.translatesAutoresizingMaskIntoConstraints = true
\n\n

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

\n\n

الخطوة 3: حل متقدم — إعادة تعريف layoutSubviews

\n\n

أصدرت Apple تصحيحًا في Xcode 11.2.1، ولكن إذا بقيت لسبب ما على الإصدار 11.2، أو كنت تريد حلاً عالميًا، فإليك ما يجب فعله.

\n\n

أنشئ فئة فرعية من UITextView وأعد تعريف الأسلوب layoutSubviews:

\n\n
import UIKit\n\nclass FixedTextView: UITextView {\n    override func layoutSubviews() {\n        super.layoutSubviews()\n        // نقوم بتنظيف الطبقة من العروض الفرعية الزائدة التي يسببها الخلل\n        self.subviews.forEach { subview in\n            if subview.isKind(of: NSClassFromString("_UITextLayoutView") ?? UIView.self) {\n        \n                

المدونات

توصيات الكتب