Kami membuat UITableView. Untuk pemula

Liburan Tahun Baru telah berlalu, tetapi keinginan saya untuk menulis artikel yang bermanfaat dan tidak terlalu - tidak! Hari ini kita akan berbicara tentang UITableView , bekerja dengan UITableViewDataSource, dan menggunakan kembali sel. Kami akan membahas cara memasang pengontrol root tanpa papan cerita, kesalahan saat bekerja dengan tabel, tata letak, dan header besar untuk UINavigationBar .


Bagi mereka yang suka lelucon lucu, saya merekam video di YouTube . Nah, di sini semuanya akan serius. Mari kita mulai.


Buat proyek kosong, beri nama apa saja yang Anda suka dan pergi ke controller. UIKit memiliki kelas UITableViewController . Anda dapat melakukan banyak tutorial di mana tabel ditampilkan persis dalam konteks kelas ini. Tetapi untuk pemahaman yang lebih baik, kami akan melakukan segalanya di basis UIViewController .


Paling sering, ketika sebuah meja dibutuhkan, UINavigationController digunakan:




Mari kita tambahkan. Dalam file AppDelegate , fungsi didFinishLaunchingWithOptions , masukkan kode berikut:


let navigationController = UINavigationController.init(rootViewController: ViewController()) self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.rootViewController = navigationController self.window?.makeKeyAndVisible() 

Program pendidikan singkat untuk alasannya: Storeboards dan Constants bagus , tetapi dalam tutorial ini kita akan mencoba melakukannya tanpa mereka. Kode ini akan mengabaikan storyboard (Anda dapat menghapusnya) dan membungkus ViewController di UINavigationController .


Akan menyenangkan untuk menetapkan judul untuk UINavigationBar . Untuk melakukan ini, kita akan pergi ke kelas ViewController (kita akan melakukan semua pekerjaan lebih lanjut di sini) dan menambahkan kode berikut ke metode viewDidLoad :


 self.view.backgroundColor = UIColor.white self.navigationItem.title = "Table" self.navigationController?.navigationBar.prefersLargeTitles = true 

Sekarang judulnya akan besar dan trendi. Menjalankan proyek, kita akan melihat hal berikut:




Membuat TableView


Tindakan persiapan selesai, kita bisa beralih ke hal utama. Di controller, buat properti UITableView . Pilih penginisialisasi yang memiliki parameter Style. Tetapkan bingkai apa pun, kami akan kembali lagi nanti. Dan untuk gaya, atur Dikelompokkan .


 let tableView = UITableView.init(frame: .zero, style: UITableView.Style.grouped) 

Saya tidak tahu mengapa nama gaya ini, tetapi itu akan memungkinkan kami untuk membuat tabel asli, seperti dalam aplikasi Pengaturan . Jika Anda membutuhkan tabel non-gaya, gunakan penginisialisasi dengan parameter bingkai saja.



Tata letak


Di sini kita akan diselamatkan oleh konstanta, tetapi kita tidak akan mencari cara yang mudah. Saya akan menunjukkan metode yang saya gunakan. Tentu saja, dia tidak berpura-pura menjadi kanonik, dan tidak perlu melakukannya. Kami mendeklarasikan fungsi yang akan mengekspos bingkai ke tampilan, dan parameter akan mengambil ukuran controller:


 private func updateLayout(with size: CGSize) { self.tableView.frame = CGRect.init(origin: .zero, size: size) } 

Anda perlu memanggil fungsi di dua tempat - dalam metode viewDidLoad dan di 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) } 

Sekarang tabel untuk setiap orientasi akan ditempatkan di layar penuh. Anda dapat menambahkan pemrosesan lain ke metode updateLayout .


Membuat UITableViewCell


Karena tutorialnya bukan tentang sel, tetapi sebuah tabel, kami tidak akan membahas penyesuaian secara detail. Mari kita buat kelas sel yang diwarisi dari basis:


 class TableViewCell: UITableViewCell { } 

Untuk menggunakan sel dalam tabel, Anda harus mendaftarkan kelas. Untuk melakukan ini, di ViewController , panggil metode berikut di tabel:


 self.tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell") 

Jika kelasnya jelas, maka pengenal tersebut layak mendapat perhatian. Dalam 99% kasus, aturan akan berfungsi:


  • " Sel dari kelas yang sama harus memiliki pengidentifikasi yang sama "

Ada beberapa situasi ketika sel-sel dari kelas yang sama membutuhkan pengidentifikasi yang berbeda, dan mereka terutama terkait dengan rendering kode dan animasi.


Sumber data


Ini adalah properti yang menunjuk ke objek yang akan mengisi tabel. Yaitu mengimplementasikan protokol UITableViewDataSource . Diperlukan dua metode:


 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {} func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} 

Yang pertama bertanggung jawab untuk jumlah sel di bagian tersebut. Kami masih memiliki satu bagian, multisection (adakah kata seperti itu?) Kami tidak akan mempertimbangkannya. Metode kedua adalah untuk mendapatkan objek sel. Ini bekerja dengan licik, jangan berpikir bahwa Anda telah menggigit pejuang!


Tapi pertama-tama, mari kita tambahkan array baris yang akan mengisi tabel.



Sekarang mari kita beralih ke menerapkan metode pertama:


 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch tableView { case self.tableView: return self.data.count default: return 0 } } 

Kami memberi tahu tabel bahwa di bagian 0 akan ada banyak sel karena ada elemen dalam array data . Metode kedua sedikit lebih rumit. Tidak mungkin hanya menginisialisasi sel, dan semua karena sistem penggunaan kembali sel. Tapi tidak perlu memarahi Apple, sebenarnya itu bagus! Untuk mendapatkan objek, Anda perlu memanggil kode berikut:


 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 } 

Metode dequeueReusableCell akan menerima objek sel dengan pengidentifikasi, dan kita akan mengetik menggunakan menggunakan kelas TableViewCell , yang seharusnya sel. textLabel adalah properti kelas dasar, tidak ada konfigurasi tambahan yang diperlukan.


Tetap menentukan dataSource untuk tabel dan metode viewDidLoad sekarang akan terlihat seperti ini:


 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) } 

Jika kami menjalankan proyek, kami akan melihat tabel diisi dengan konten:




Gunakan kembali


Sejauh ini, semuanya tampak beres. Mari kita tambahkanIndikator pengungkapan untuk salah satu sel. Ini adalah aksesori yang pasti Anda lihat di iOS:



Katakanlah tugasnya adalah mengatur indikator hanya untuk sel pertama. Hal pertama yang terlintas dalam pikiran adalah menambahkan sederhana jika ke metode cellForRowAt :


 if indexPath.row == 0 { cell.accessoryType = .disclosureIndicator } 

Tapi musuh bersembunyi! Mari kita jalankan proyek, dan gulir tabel dari layar:



Indikator muncul untuk yang pertama, tetapi muncul secara serampangan untuk sel-sel lain! Ini digunakan kembali - sel diambil yang lebih nyaman dalam memori (penjelasan yang bagus untuk pemula, kan?) Dan dikonfigurasi sesuai dengan metode. Kadang-kadang terjadi bahwa sel dengan indikator ditarik. Akibatnya, kami memiliki bug seperti itu. Apa yang harus dilakukan


Semuanya sederhana. Ada dua solusi yang mungkin. Yang pertama adalah di blok lain dan pada dasarnya menyiratkan konfigurasi yang jelas dari sel mana pun. Metode akan terlihat seperti ini:


 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 } 

Ada cara lain - untuk menerapkan metode prepForReuse pada sel. Seperti namanya, metode ini dipanggil sebelum digunakan kembali. Yang perlu Anda lakukan adalah mengatur ulang sel ke default. Kode ini terlihat seperti ini:


 class TableViewCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() self.accessoryType = .none } } 

Ada banyak nuansa yang terkait dengan penggunaan kembali. Misalnya, tugas memuat gambar untuk sel di latar belakang dengan pagination, tinggi adaptif, penghapusan dan penyisipan animasi. Tetapi lebih lanjut tentang itu di bagian kedua, jika tangan saya mencapai)


Bagi para pencari


Saya mencoba merekam tutorial di saluran saya secara teratur. Anda dapat menemukan video tentang cara menggambar kode atau cara membuat pengontrol pemutar Musik Apple , serta video di artikel ini:


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


All Articles