مراسلة دائرة الرقابة الداخلية: تحليل إيجابيات وسلبيات ، وأفضل الممارسات



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

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

لنبدأ مع أوجه القصور وتحليل ما إذا كانت جميعها لا تزال ذات صلة.

القصور


1. يواجه الأطفال صعوبة في إدارة التعارضات عند دمج التغييرات


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

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

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

2. القصص المصورة منع إعادة استخدام رمز


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

أولاً ، قم بإنشاء فئة XibView الأساسية ، المسؤولة عن تقديم UIView تم إنشاؤها في Xib في لوحة العمل:

 @IBDesignable class XibView: UIView { var contentView: UIView? } 

سيقوم XibView بتحميل UIView من Xib إلى contentView وإضافته كملف فرعي. نحن نفعل هذا في طريقة setup() :

 private func setup() { guard let view = loadViewFromNib() else { return } view.frame = bounds view.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(view) contentView = view } 

تبدو طريقة loadViewFromNib() كما يلي:

 private func loadViewFromNib() -> UIView? { let nibName = String(describing: type(of: self)) let nib = UINib(nibName: nibName, bundle: Bundle(for: XibView.self)) return nib.instantiate(withOwner: self, options: nil).first as? UIView } 

يجب استدعاء طريقة setup() في أدوات التهيئة:

 override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } 

فئة XibView جاهزة. طرق العرض التي تمت إعادة استخدامها ، والتي يتم عرض مظهرها في ملف Xib ، XibView من XibView :

 final class RedView: XibView { } 


إذا أضفت الآن UIView جديدة إلى Storyboard وقمت بتعيين فئتها على RedView ، فسيتم عرض كل شيء بنجاح:

يحدث إنشاء مثيل لـ RedView في التعليمات البرمجية بالطريقة المعتادة:

 let redView = RedView() 

التفاصيل المفيدة الأخرى التي لا يمكن لأي شخص معرفتها هي القدرة على إضافة ألوان إلى دليل .xcassets . يتيح لك هذا إمكانية تغييرها على مستوى العالم في جميع Twitter و Xibs حيث يتم استخدامها.

لإضافة لون ، انقر فوق "+" في أسفل اليسار وحدد "مجموعة ألوان جديدة":

حدد الاسم واللون المطلوبين:

سيظهر اللون الذي تم إنشاؤه في قسم "الألوان المسماة":

بالإضافة إلى ذلك ، يمكن الحصول عليها في الكود:

 innerView.backgroundColor = UIColor(named: "BackgroundColor") 

3. لا يمكنك استخدام أدوات تهيئة مخصصة لـ UIViewControllers تم إنشاؤها في لوحة العمل


في حالة لوحة العمل ، لا يمكننا تمرير التبعيات في UIViewControllers . عادة ما يبدو مثل هذا:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "detail", let detailVC = segue.destination as? DetailViewController else { return } let object = Object() detailVC.object = object } 

يمكن تنفيذ هذا الكود بشكل أفضل باستخدام نوع ثابت لتمثيل المعرفات أو الأدوات مثل SwiftGen و R.swift ، أو ربما Perform . ولكن بهذه الطريقة نتخلص فقط من القيم الحرفية ونضيف السكر النحوي ، ولا نحل المشاكل التي تنشأ:

  • كيف أعرف كيف DetailViewController تكوين DetailViewController في المثال أعلاه؟ إذا كنت جديدًا في المشروع ولم تكن لديك هذه المعرفة ، فسيتعين عليك فتح ملف مع وصف وحدة التحكم هذه ودراستها.
  • DetailViewController تعيين خصائص DetailViewController بعد التهيئة ، مما يعني أنها يجب أن تكون اختيارية. من الضروري التعامل مع الحالات التي تكون فيها أي خاصية nil ، وإلا فقد يتعطل التطبيق في أكثر الأوقات غير مناسبة. يمكنك تعليم الخصائص على أنها موسعة ضمنيًا اختيارية ( var object: Object! ) ، ولكن لن يتغير الجوهر.
  • يجب أن يتم تمييز الخصائص كـ var ، وليس let . إذاً الموقف ممكن عندما يريد شخص من الخارج تغييره. DetailViewController يجب التعامل مع مثل هذه الحالات.

تم وصف حل واحد في هذه المقالة .

4. مع نمو لوحة العمل ، يصبح التنقل فيها أكثر صعوبة


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

لقد قمنا بتعيين قيم الحقول المطلوبة في Attributes Inspector - هذا هو اسم ملف لوحة العمل ، وإذا لزم الأمر ، هو معرف المرجع الذي يتوافق مع معرف لوحة العمل للشاشة المرغوبة. بشكل افتراضي ، سيتم تحميل وحدة تحكم العرض الأولي :

إذا حددت اسمًا غير صالح في حقل Storyboard أو تشير إلى معرف Storyboard غير موجود ، فسيحذرك Xcode من ذلك في مرحلة الترجمة.

5. Xcode يبطئ عند تحميل القصص المصورة


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

6. القصص المصورة هشة ، يمكن أن يتسبب الخطأ في تعطل التطبيق في وقت التشغيل


نقاط الضعف الرئيسية:

  • الأخطاء في UICollectionViewCell و UICollectionViewCell .
  • أخطاء في معرفات المقاطع.
  • باستخدام فئة فرعية من UIView التي لم تعد موجودة.
  • تزامن IBActions و IBActions مع رمز.

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

يمكنك تقليل احتمالية حدوث الأخطاء عن طريق التخلص من سلسلة الأحرف في الكود. لهذا الغرض ، يمكن تعيين UICollectionViewCell و UICollectionViewCell لأسماء فئات الخلية نفسها: على سبيل المثال ، سيكون معرف ItemTableViewCell هو السلسلة "ItemTableViewCell". في الكود ، نحصل على الخلية مثل هذا:

 let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ItemTableViewCell.self)) as! ItemTableViewCell 

يمكنك إضافة الوظيفة العامة المقابلة إلى UITableView :

 extension UITableView { open func dequeueReusableCell<T>() -> T where T: UITableViewCell { return dequeueReusableCell(withIdentifier: String(describing: T.self)) as! T } } 

ثم يصبح الحصول على الخلية أسهل:

 let cell: ItemTableViewCell = tableView.dequeueReusableCell() 

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

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

 protocol SegueHandler { associatedtype SegueIdentifier: RawRepresentable } 

سيحتاج UIViewController الذي يدعم هذا البروتوكول إلى تحديد نوع متداخل يحمل نفس الاسم. إنه يسرد جميع معرّفات الشرائح التي يمكن لـ UIViewController معالجتها:

 extension StartViewController: SegueHandler { enum SegueIdentifier: String { case signIn, signUp } } 

بالإضافة إلى ذلك ، في ملحق بروتوكول SegueHandler ، نعرّف وظيفتين: واحدة تقبل UIStoryboardSegue وتُرجع قيمة SegueIdentifier المقابلة ، والآخر يستدعي ببساطة performSegue ، مع إدخال مدخلات SegueIdentifier :

 extension SegueHandler where Self: UIViewController, SegueIdentifier.RawValue == String { func performSegue(withIdentifier segueIdentifier: SegueIdentifier, sender: AnyObject?) { performSegue(withIdentifier: segueIdentifier.rawValue, sender: sender) } func segueIdentifier(for segue: UIStoryboardSegue) -> SegueIdentifier { guard let identifier = segue.identifier, let identifierCase = SegueIdentifier(rawValue: identifier) else { fatalError("Invalid segue identifier \(String(describing: segue.identifier)).") } return identifierCase } } 

والآن في UIViewController الذي يدعم البروتوكول الجديد ، يمكنك العمل مع prepare(for:sender:) كما يلي:

 extension StartViewController: SegueHandler { enum SegueIdentifier: String { case signIn, signUp } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segueIdentifier(for: segue) { case .signIn: print("signIn") case .signUp: print("signUp") } } } 

وتشغيل segue مثل هذا:

 performSegue(withIdentifier: .signIn, sender: nil) 

إذا أضفت معرفًا جديدًا إلى SegueIdentifier ، SegueIdentifier Xcode بالتأكيد على SegueIdentifier في switch/case .

هناك خيار آخر للتخلص من القيم الحرفية للسلسلة ، مثل معرفات المعرفات وغيرها ، وهو استخدام أدوات إنشاء الكود مثل R.swift .

7. القصص المصورة أقل مرونة من الرمز.


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

8. القصص المصورة لا تسمح بتغيير نوع UIViewControllers الخاص


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

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


هذا هو واجهة البناء ومحلل القصص المصورة. مثل هذه الحالات نادرة وغالبًا ما يتم التحايل عليها بواسطة حلول أخرى.

10. مراجعة مدونة متطورة


ضع في اعتبارك أن مراجعة التعليمات البرمجية ليست بحثًا عن الأخطاء حقًا. نعم ، إنها موجودة في عملية عرض الكود ، لكن الهدف الرئيسي هو تحديد نقاط الضعف التي يمكن أن تخلق مشاكل على المدى الطويل. بالنسبة إلى القصص المصورة ، هذا هو عمل Auto Layout بشكل أساسي. لا ينبغي أن يكون هناك أي غموض في غير محله . للعثور عليهم ، استخدم فقط البحث في XML في Storyboard للخطوط "ambiguous =" YES "" و "misplaced =" YES "" أو فقط افتح Storyboard في Interface Builder وابحث عن النقاط الحمراء والصفراء:

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

كل شيء آخر - مطابقة موقع وحجم العناصر مع التصميم والتجليد الصحيح لـ IBActions و IBActions - ليس للمراجعة البرمجية.

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

يؤدي


في قائمة عيوب القصص المصورة ، تركت 4 عناصر (بترتيب تنازلي حسب قيمتها):

  1. يواجه المرسلون صعوبة في إدارة الصراعات عند دمج التغييرات.
  2. القصص المصورة أقل مرونة من الشفرة.
  3. القصص المصورة هشة ، يمكن أن يؤدي الخطأ إلى تعطل وقت التشغيل.
  4. لا يمكنك استخدام أدوات تهيئة مخصصة لـ UIViewControllers تم إنشاؤها في لوحة العمل.

الفوائد


1. التصور من واجهة المستخدم والقيود


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

بشكل منفصل ، لاحظ التخطيط التلقائي. هذه أداة قوية ومفيدة للغاية ، والتي بدونها سيكون من الصعب إنشاء تطبيق يدعم جميع أحجام الشاشة المختلفة. يسمح لك Interface Builder برؤية نتيجة العمل مع Auto Layout دون تشغيل التطبيق ، وإذا لم تتوافق بعض القيود مع المخطط العام ، فسوف يحذرك Xcode على الفور من ذلك. بالطبع ، هناك حالات عندما يتعذر على Interface Builder توفير السلوك الضروري لبعض الواجهات الديناميكية والمعقدة للغاية ، ثم يتعين عليك الاعتماد على الكود. ولكن حتى في مثل هذه الحالات ، يمكنك القيام بمعظمها في Interface Builder وإضافتها ببضع أسطر من التعليمات البرمجية.

دعونا نلقي نظرة على بعض الأمثلة التي توضح الميزات المفيدة لـ Interface Builder.

الجداول الديناميكية القائمة على UIStackView


إنشاء UIViewController جديد ، إضافة شاشة كاملة UIScrollView :

في UIStackView UIScrollView أضف UIStackView عموديًا ، UIStackView على الحواف وقم بتعيين الطول والعرض مساويا لـ UIScrollView . عند هذا الارتفاع ، حدد الأولوية = منخفض (250) :

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



يمكننا أيضًا أن نجعل الخلايا تتكيف مع حجم محتواها. أضف UILabel إلى كل خلية ، UILabel بالحواف:

من الواضح بالفعل كيف سيبدو كل هذا في وقت التشغيل. يمكنك إرفاق أي إجراءات بالخلايا ، على سبيل المثال ، التبديل إلى شاشة أخرى. وكل هذا دون سطر واحد من التعليمات البرمجية.
علاوة على ذلك ، إذا قمت بتعيين hidden = true لـ UIView من UIStackView ، فلن تخفيها فقط ، ولكنها لن UIStackView أيضًا. سوف UIStackView تلقائيا إعادة حساب أحجامها:



خلايا التحجيم الذاتي


في عارض الحجم بالجدول ، قم بتعيين Row Height = Automatic ، و Estimate - على بعض القيمة المتوسطة:

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

نتيجة لذلك ، عند بدء تشغيل التطبيق ، سنرى أن كل شيء يتم عرضه بشكل صحيح:

الجدول التحجيم الذاتي


تحتاج إلى تطبيق سلوك هذا الجدول:



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

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

في هذه المرحلة ، لا يعرف Interface Builder بعدًا الارتفاع الذي سيكون عليه الجدول ، فهو يعرف فقط القيمة القصوى التي تساوي 200 (من قيود الارتفاع). كما ذكر سابقًا ، حجم المحتوى الجوهري لا يساوي محتويات الجدول. ومع ذلك ، لدينا القدرة على تعيين العنصر النائب في حقل الحجم الجوهري :

هذه القيمة صالحة فقط أثناء العمل مع Interface Builder. بالطبع ، لا يجب أن يكون حجم المحتوى الجوهري مساويًا لهذه القيمة في وقت التشغيل. قلنا للتو Interface Builder أن كل شيء تحت السيطرة.

بعد ذلك ، قم بإنشاء فئة فرعية جديدة من جدول CustomTableView :

 final class CustomTableView: UITableView { override var contentSize: CGSize { didSet { invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return contentSize } } 

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

يمكن دمج كل من ميزات Interface Builder الثلاثة مع بعضها البعض. يضيفون مزيدًا من المرونة إلى خيارات تنظيم المحتوى دون الحاجة إلى قيود إضافية أو أي UIView .

2. القدرة على رؤية نتائج أعمالهم على الفور


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

إن استخدام @IBInspectable يكشف عن هذه الفائدة بشكل أكثر إثارة للاهتمام. أضف UILabel واثنين من الخصائص إلى RedView :

 final class RedView: XibView { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var subtitleLabel: UILabel! @IBInspectable var title: String = "" { didSet { titleLabel.text = title } } @IBInspectable var subtitle: String = "" { didSet { subtitleLabel.text = subtitle } } } 

سيظهر RedView في " RedView لـ RedView - Title Subtitle ، والذي وضعنا علامة عليه في @IBInspectable :

إذا حاولنا إدخال قيم في هذه الحقول ، فسنرى على الفور كيف سيبدو كل شيء في وقت التشغيل:



يمكنك التحكم في أي شيء: cornerRadius ، borderWidth ، borderColor . على سبيل المثال ، نمد فئة UIView الأساسية:

 extension UIView { @IBInspectable var cornerRadius: CGFloat { set { layer.cornerRadius = newValue } get { return layer.cornerRadius } } @IBInspectable var borderWidth: CGFloat { set { layer.borderWidth = newValue } get { return layer.borderWidth } } @IBInspectable var borderColor: UIColor? { set { layer.borderColor = newValue?.cgColor } get { return layer.borderColor != nil ? UIColor(cgColor: layer.borderColor!) : nil } } @IBInspectable var rotate: CGFloat { set { transform = CGAffineTransform(rotationAngle: newValue * .pi/180) } get { return 0 } } } 

نرى أن "مفتش RedView الكائن RedView اكتسب 4 حقول جديدة ، والتي يمكنك الآن اللعب مع:



3. معاينة جميع أحجام الشاشة في وقت واحد


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

ندعو محرر المساعد ، في النقر على الجزء الأول من لوحة الانتقال ، حدد معاينة -> إعدادات. لوحة التخزين (على سبيل المثال):

في البداية ، نرى شاشة واحدة فقط ، ولكن يمكننا إضافة الكثير حسب الحاجة من خلال النقر على "+" في الركن الأيسر السفلي واختيار الأجهزة اللازمة من القائمة:

بالإضافة إلى ذلك ، إذا كانت لوحة العمل تدعم عدة لغات ، يمكنك أن ترى كيف ستبدو الشاشة المحددة مع كل منها:

يمكن اختيار اللغة لجميع الشاشات في وقت واحد ، ولكل منها على حدة.

4. إزالة القالب رمز واجهة المستخدم


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

5. حجم الطبقات


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

تقوم فئات الحجم بتصنيف ارتفاع (h) وعرض (w) لشاشات الجهاز من حيث الحجم الصغير والمنتظم ( C و R ). على سبيل المثال ، يحتوي iPhone 8 على فئة حجم (wC hR) في اتجاه عمودي و (wC hC) في المناظر الطبيعية ، و iPhone 8 Plus لديه (wC hR) و (wR hC) على التوالي. يمكن العثور على بقية الأجهزة هنا .

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

على سبيل المثال ، قم بتكوين حجم الخط حسب فئة الحجم. نختار جهاز iPhone 8 Plus للعرض في لوحة العمل في اتجاه عمودي ونضيف شرطًا جديدًا font: إذا كان العرض منتظمًا (اضبط الباقي على "أي") ، فينبغي أن يكون حجم الخط 37:

الآن ، إذا قمنا بتغيير اتجاه الشاشة ، فسوف يزداد حجم الخط - ستعمل حالة جديدة ، نظرًا لأن iPhone 8 Plus لديه فئة حجم (wR hC) في اتجاه أفقي . في لوحة العمل ، بناءً على فئة الحجم ، يمكنك أيضًا إخفاء طرق العرض وتمكين / تعطيل القيود وتغيير قيمتها constantوغير ذلك الكثير. اقرأ المزيد حول كيفية القيام بكل هذا هنا .

في لقطة الشاشة أعلاه ، تجدر الإشارة إلى اللوحة السفلية مع اختيار الجهاز لعرض الشكل. يسمح لك بالتحقق بسرعة من قابلية واجهة المستخدم للتكيف على أي جهاز وأي اتجاه للشاشة ، كما يعرض فئة حجم التكوين الحالي (بجانب اسم الجهاز). من بين أشياء أخرى ، على اليمين يوجد زر « Vary for Traits". الغرض منه هو تمكين اختلافات السمات فقط لفئة محددة من العرض أو الارتفاع أو العرض والارتفاع في نفس الوقت. على سبيل المثال، من خلال تحديد باد إلى الفراش حجم الطبقة (WR الموارد البشرية) ، ودفع «فاري عن الصفات» ووضع علامة الاختيار في العرض و الارتفاع . الآن ، سيتم تطبيق جميع تغييرات التنسيق اللاحقة فقط على الأجهزة التي تحتوي على (wR hR) حتى يتم النقر فوق Done Varying .

استنتاج

#
القصور
الفوائد
1
من الصعب الحكم الصراعات
التصور واجهة المستخدم والقيود
2
ليس مرنًا مثل الكود
القدرة على رؤية نتيجة أفعالك على الفور
3
خطأ يمكن أن يؤدي إلى تعطل في وقت التشغيل.
معاينة جميع أحجام الشاشة في وقت واحد
4
لا يمكنك استخدام مهيئات مخصصة ل UIViewControllers
إزالة القالب رمز واجهة المستخدم
5
فصول الحجم
رأينا أن القصص المصورة لها نقاط القوة والضعف. رأيي هو أنه يجب أن لا ترفض تماما استخدامها. عند استخدامها بشكل صحيح ، فإنها تحقق فوائد كبيرة وتساعد على حل المهام بفعالية. تحتاج فقط إلى معرفة كيفية تحديد الأولويات ونسيان الحجج مثل "أنا لا أحب القصص المصورة" أو "أنا معتاد على القيام بذلك."

Source: https://habr.com/ru/post/ar456086/


All Articles