ios - UITableView 如何与 UITableViewDataSource 一起工作?
问题描述
我是 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
?
解决方案
许多类UIKit
使用这种“数据源”模式来填充自己的数据。除了UITableView
, 还有UICollectionView
,UIPickerView
和UIPageViewControllerDataSource
, 仅举几例。这个答案中所说的也可以应用于这些类。
与其让你一次性提供所有数据,不如UITableView
只在需要时才请求数据。这是因为有时数据可能在 Internet 上,一次获取所有数据可能需要很长时间,不是吗?
好的,那么表格视图应该向谁询问数据?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!
}
注意,虽然上面的两个数据源方法确实有名字,但是用andtableView
来称呼它们更有用,这也是人们经常做的事情。numberOfRowsInSection
cellForRowAt
不太重要(对于这个问题),在这些方法中,tableView
指的是参数,而不是你的类中声明的属性。要引用您的类中声明的属性,您需要self.tableView
.
表格视图将在适当的时候调用这些方法,同时提供参数。例如,cellForRowAt
当它需要显示一个新的单元格时会被调用。
我发现你对你的一些误解:
tableView.dataSource
是情节提要中的一个变量
该dataSource
属性在 中声明UITableView
。您只能在故事板(或更准确地说,Xcode 的界面生成器)中看到它。dataSource
并不是真正“来自”故事板。
该变量
tableView
作为第一个参数传递给两个函数tableView
,而不是在定义中使用。
这tableView
是参数的名称。你没有通过任何东西。请记住,您正在声明这些方法,并且您不应该传递参数。调用者 - 表视图 - 是。
此外,您使用的是tableView
in 参数cellForRowAt
,因为该参数隐藏了tableView
in 声明的属性ChatViewController
。
推荐阅读
- amazon-web-services - api网关中的2个api如何共享相同的lambda函数但不同的环境变量
- parsing - 有没有一种聪明的方法可以在 ANTLR 中使用不同类型的括号
- excel - 需要在excel中转换加3个月
- postgresql - 部分唯一索引不适用于冲突子句 PostgreSQL
- sql - 如果不存在则插入数据的过程 pl sql
- git-p4 - 仓库不同时的 git-p4 克隆
- reactjs - 如果第一个请求返回 400,则 Axios 第二个请求失败并出现 CORS 错误,但如果返回 200,则工作正常
- python-3.x - 在 python 3 中显示链接列表时的特殊输出
- bitbucket - 如何在 bitbucket 上解决这个拉取请求问题?我们不能让你看到这个页面 要访问这个页面
- regex - 在 bash 如何将 extglobed 文件名放入数组中?