
قامت 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 عناصر (بترتيب تنازلي حسب قيمتها):
- يواجه المرسلون صعوبة في إدارة الصراعات عند دمج التغييرات.
- القصص المصورة أقل مرونة من الشفرة.
- القصص المصورة هشة ، يمكن أن يؤدي الخطأ إلى تعطل وقت التشغيل.
- لا يمكنك استخدام أدوات تهيئة مخصصة لـ
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 .استنتاج
رأينا أن القصص المصورة لها نقاط القوة والضعف. رأيي هو أنه يجب أن لا ترفض تماما استخدامها. عند استخدامها بشكل صحيح ، فإنها تحقق فوائد كبيرة وتساعد على حل المهام بفعالية. تحتاج فقط إلى معرفة كيفية تحديد الأولويات ونسيان الحجج مثل "أنا لا أحب القصص المصورة" أو "أنا معتاد على القيام بذلك."