Как UITableView работает с UITableViewDataSource? - PullRequest
0 голосов
/ 19 апреля 2020

Я новичок в Swift и пытаюсь понять, как tableView.dataSource = self относится к функциям в расширении:

class ChatViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var messageTextfield: UITextField!

    var messages: [Message] = [
        Message(sender: "email", body: "Hey!" ),
        Message(sender: "email", body: "Hello!" ),
        Message(sender: "email", body: "What's up!" ),
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        title = K.appName
        navigationItem.hidesBackButton = true
        tableView.dataSource = self
    }

    @IBAction func sendPressed(_ sender: UIButton) {
    }


    @IBAction func logOutPressed(_ sender: UIBarButtonItem) {
        do {
          try Auth.auth().signOut()
            navigationController?.popToRootViewController(animated: true)
        } catch let signOutError as NSError {
          print ("Error signing out: %@", signOutError)
        }
    }
}


extension ChatViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        print(section)
        return messages.count
    }

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

tableView.dataSource - это переменная из раскадровки, которая отличается из двух функций, определенных в расширении под названием tableView, которое, как оказалось, имеет одно и то же имя. Переменная tableView передается в качестве первого аргумента обеим функциям tableView и не используется в определении.

Какова связь между переменной tableView и функцией tableView и как переменная используется в функции, даже если ее нет в определении функции? И что делает tableView.dataSource = self? 1014 *

1 Ответ

2 голосов
/ 19 апреля 2020

Многие классы в 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...