لقد مرت عطل رأس السنة الميلادية ، لكن رغبتي في كتابة مقالات مفيدة وليست مفيدة للغاية - لا! اليوم سنتحدث عن UITableView ، والعمل مع UITableViewDataSource ، وإعادة استخدام الخلايا. سنغطي كيفية تثبيت وحدة التحكم في الجذر دون لوحة العمل ، والأخطاء عند العمل مع الجدول والتخطيط ورأس كبير لـ UINavigationBar .
بالنسبة لأولئك الذين يحبون النكات المضحكة ، قمت بتسجيل مقطع فيديو على YouTube . حسنا ، هنا كل شيء سيكون خطيرا. لنبدأ.
إنشاء مشروع فارغ ، وتسميته ما تريد وانتقل إلى وحدة تحكم. UIKit لديه فئة UITableViewController. يمكنك جوجل الكثير من البرامج التعليمية حيث يتم عرض الجدول بالضبط في سياق هذه الفئة. ولكن من أجل فهم أفضل ، سنفعل كل شيء في قاعدة UIViewController .
في معظم الأحيان ، عندما تكون هناك حاجة إلى جدول ، يتم استخدام UINavigationController :

دعونا إضافته. في ملف AppDelegate ، وظيفة didFinishLaunchingWithOptions ، أدخل الكود التالي:
let navigationController = UINavigationController.init(rootViewController: ViewController()) self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.rootViewController = navigationController self.window?.makeKeyAndVisible()
برنامج تعليمي قصير عن السبب: تكون المتاجر والثوابت جيدة ، ولكن في هذا البرنامج التعليمي سنحاول الاستغناء عنها. سيتجاهل هذا الرمز لوحة العمل (يمكنك إزالته) ولف ViewController في UINavigationController .
سيكون من الجيد تعيين عنوان لـ UINavigationBar . للقيام بذلك ، سوف نذهب إلى فئة ViewController (سنفعل المزيد من العمل هنا) وإضافة الكود التالي إلى طريقة viewDidLoad :
self.view.backgroundColor = UIColor.white self.navigationItem.title = "Table" self.navigationController?.navigationBar.prefersLargeTitles = true
الآن سيكون العنوان كبيرًا وعصريًا. تشغيل المشروع ، سنرى ما يلي:

جعل TableView
اكتمال الإجراءات التحضيرية ، يمكننا الانتقال إلى الشيء الرئيسي. في وحدة التحكم ، قم بإنشاء خاصية UITableView . اختر مُهيئًا يحتوي على معلمة نمط. قم بتعيين أي إطار ، سنعود إليه لاحقًا. وللأسلوب ، مجموعة مجمعة .
let tableView = UITableView.init(frame: .zero, style: UITableView.Style.grouped)
ليس لدي أي فكرة عن سبب اسم هذا النمط ، ولكنه سيسمح لنا بإنشاء جدول أصلي ، كما هو الحال في تطبيق الإعدادات . إذا كنت بحاجة إلى جدول غير منمق ، استخدم أداة التهيئة مع معلمة الإطار فقط.

تخطيط
هنا كنا قد أنقذنا الثابت ، لكننا لن نبحث عن طرق سهلة. سأظهر الطريقة التي أستخدمها. بالطبع ، هو لا يتظاهر بأنه قانوني ، وليس من الضروري أن يفعل ذلك. نعلن عن وظيفة من شأنها أن تعرض الإطار إلى المشاهدات ، وسوف تأخذ المعلمة حجم وحدة التحكم:
private func updateLayout(with size: CGSize) { self.tableView.frame = CGRect.init(origin: .zero, size: size) }
تحتاج إلى استدعاء الوظيفة في مكانين - في طريقة viewDidLoad وفي viewWillTransition :
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { (contex) in self.updateLayout(with: size) }, completion: nil) }
الآن سيتم وضع الجدول لأي اتجاه في وضع ملء الشاشة. يمكنك إضافة معالجة أخرى إلى أسلوب updateLayout .
صنع UITableViewCell
نظرًا لأن البرنامج التعليمي لا يتعلق بالخلايا ، بل هو جدول ، فلن نتناول بالتفصيل التخصيص. لنجعل فئة الخلية الموروثة من القاعدة:
class TableViewCell: UITableViewCell { }
لاستخدام الخلية في الجدول ، تحتاج إلى تسجيل الفصل. للقيام بذلك ، في ViewController ، استدعاء الطريقة التالية على الجدول:
self.tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")
إذا كان الفصل واضحًا ، فالمعرف يستحق الاهتمام. في 99 ٪ من الحالات ، ستعمل القاعدة:
- " يجب أن تحتوي خلايا نفس الفئة على المعرف نفسه "
هناك حالات قليلة جدًا عندما تحتاج خلايا من نفس الفئة إلى معرفات مختلفة ، وترتبط أساسًا بتقديم الرموز والرسوم المتحركة.
مصدر البيانات
هذه خاصية تشير إلى الكائن الذي سيملأ الجدول. أي تطبيق بروتوكول UITableViewDataSource . هناك طريقتان مطلوبة:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {} func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
الأول مسؤول عن عدد الخلايا في القسم. لا يزال لدينا قسم واحد ، متعدد الأقسام (هل هناك مثل هذه الكلمة؟) لن نفكر فيها. الطريقة الثانية هي الحصول على كائن الخلية. إنه يعمل بمكر ، لا تظن أنك قد قاتلت مقاتلًا!
ولكن أولاً ، دعنا نضيف مجموعة من الصفوف التي ستملأ الجدول.

الآن دعنا ننتقل إلى تنفيذ الطريقة الأولى:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch tableView { case self.tableView: return self.data.count default: return 0 } }
نقول للجدول أنه في القسم 0 سيكون هناك العديد من الخلايا كما توجد عناصر في صفيف البيانات . الطريقة الثانية هي أكثر تعقيدا قليلا. من المستحيل ببساطة تهيئة الخلية ، وكل ذلك بسبب نظام إعادة استخدام الخلايا. ولكن لا حاجة إلى تأنيب أبل ، إنها في الحقيقة جيدة! للحصول على الكائن ، تحتاج إلى استدعاء الرمز التالي:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell cell.textLabel?.text = self.data[indexPath.row] return cell }
ستتلقى طريقة dequeueReusableCell كائن الخلية بواسطة المعرف ، وسوف نقوم باستخدام نوع الكتابة إلى فئة TableViewCell ، والتي يجب أن تكون الخلية. textLabel هي خاصية من الدرجة الأساسية ؛ لا يلزم تكوين إضافي.
يبقى تحديد مصدر البيانات للجدول ويجب الآن أن تبدو طريقة viewDidLoad بالشكل التالي:
override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.white self.navigationItem.title = "Table" self.navigationController?.navigationBar.prefersLargeTitles = true self.view.addSubview(self.tableView) self.tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell") self.tableView.dataSource = self self.updateLayout(with: self.view.frame.size) }
إذا قمنا بتشغيل المشروع ، فسوف نرى جدولًا ممتلئًا بالمحتوى:

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

دعنا نقول أن المهمة هي تعيين المؤشر فقط للخلية الأولى. أول ما يتبادر إلى الذهن هو إضافة طريقة بسيطة إلى طريقة cellForRowAt :
if indexPath.row == 0 { cell.accessoryType = .disclosureIndicator }
لكن العدو يختبئ! لنشغل المشروع ، وقم بالتمرير من على الشاشة:

ظهر المؤشر لأول مرة ، لكنه يظهر بشكل عشوائي للخلايا الأخرى! هذا هو إعادة الاستخدام - تؤخذ خلية أكثر ملاءمة في الذاكرة (شرح كبير للمبتدئين ، أليس كذلك؟) وتكوينها وفقا للطريقة. في بعض الأحيان يحدث أن يتم سحب خلية مع مؤشر. نتيجة لذلك ، لدينا مثل هذا الخطأ. ما يجب القيام به
كل شيء بسيط. هناك حلان ممكنان. الأول في الكتلة الأخرى ويشير بشكل أساسي إلى التكوين الواضح لأي خلية. ستبدو الطريقة هكذا:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell cell.textLabel?.text = self.data[indexPath.row] if indexPath.row == 0 { cell.accessoryType = .disclosureIndicator } else { cell.accessoryType = .none } return cell }
هناك طريقة أخرى - لتطبيق طريقة preparForReuse على الخلية. كما يوحي الاسم ، يتم استدعاء الأسلوب قبل إعادة الاستخدام. كل ما عليك القيام به هو إعادة تعيين الخلية إلى الافتراضي. الرمز يشبه هذا:
class TableViewCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() self.accessoryType = .none } }
هناك العديد من الفروق الدقيقة المرتبطة بإعادة الاستخدام. على سبيل المثال ، مهمة تحميل الصور لخلية في الخلفية مع ترقيم الصفحات والارتفاع التكيفي والحذف المتحرك والإدراج. ولكن المزيد عن ذلك في الجزء الثاني ، إذا وصلت يدي)
للباحثين
أحاول تسجيل برنامج تعليمي بانتظام على قناتي . يمكنك العثور على مقاطع فيديو حول كيفية رسم التعليمات البرمجية أو كيفية إنشاء جهاز تحكم Apple Music Player ، بالإضافة إلى مقطع فيديو حول هذه المقالة: