Многие классы в UIKit
используют этот шаблон «источника данных» для заполнения себя данными. Кроме UITableView
, есть также UICollectionView
, UIPickerView
и UIPageViewControllerDataSource
, и это лишь некоторые из них. То, что сказано в этом ответе, также может быть применено и к этим классам.
Вместо того, чтобы заставлять давать все данные одновременно, UITableView
запрашивает данные только тогда, когда это необходимо. Это потому, что иногда данные могут быть, скажем, на Inte rnet, их извлечение all за один раз может занять много времени, не так ли?
Хорошо, так кто же должно ли табличное представление запрашивать данные? dataSource
! Как табличное представление знает, что его источник данных может ответить на его вопросы? Убедившись, что источник данных соответствует протоколу UITableViewDataSource
, который определяет несколько методов.
Следовательно, tableView.dataSource = self
говорит:
Эй tableView
, если Вы хотите запросить данные, просто спросите self
(ChatViewController
)!
Реализуя UITableViewDataSource
, мы говорим, что этот класс может дать ответы на вопросы табличного представления .
Как мы на самом деле предоставляем ответы? Реализуя методы источника данных!
// this is asking:
// for section number "section" the table view "tableView", how many rows does it have?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(section)
return messages.count // we answer: it has as many rows as "messages.count"
}
// this is asking:
// for the row at the index path "indexPath", in the table view "tableView",
// what UITableViewCell should I display?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: K.cellIdentifier, for: indexPath)
cell.textLabel?.text = messages[indexPath.row].body
return cell // we answer: you should display this cell!
}
Обратите внимание, что хотя два вышеупомянутых метода источника данных действительно имеют имя tableView
, более полезно ссылаться на них как numberOfRowsInSection
и cellForRowAt
, и это также часто делают люди.
Менее важно (для этого вопроса), в этих методах tableView
относится к параметру, а не к свойству, объявленному в вашем классе. Чтобы обратиться к свойству, объявленному в вашем классе, вам нужно self.tableView
.
Табличное представление будет вызывать эти методы всякий раз, когда это необходимо, также предоставляя параметры. Например, cellForRowAt
будет вызываться, когда необходимо отобразить новую ячейку.
Несколько ваших заблуждений, которые я заметил:
tableView.dataSource
- это переменная из раскадровки
Свойство dataSource
объявлено в UITableView
. Вы просто можете увидеть это в раскадровке (или, точнее, в Xcode Interface Builder). dataSource
на самом деле не "из" раскадровки.
Переменная tableView
передается в качестве первого аргумента обеим функциям tableView
и не используется в определении.
Это tableView
является именем параметра. Вы ничего не передаете. Помните, что вы объявляете эти методы, и вы не должны передавать параметры. Вызывающий объект - представление таблицы - is.
Кроме того, вы используете параметр tableView
в cellForRowAt
, поскольку этот параметр скрывает свойство tableView
, объявленное в ChatViewController
.