委托和数据源在不同的类中可能吗? - UITableView



在使用UITableView时,有两种类型的方法,即数据源和委托仍然应该连接到同一个父视图控制器类

有没有办法在不同的类中定义委托和数据源?

为什么我们需要分离作为代表和数据源?

注意:此问题适用于UICollectionView和类似对象

正如在其他响应中对委派模式的充分解释,我们可以将表视图数据源和委托声明为不同的对象,以避免大规模视图控制器并实现精益视图控制器。

下面是使用委托设计模式的代码示例。

import UIKit
// MARK: Cell
class ItemCell: UITableViewCell{
var label: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 20))
label.textColor = .black
label.backgroundColor = .yellow
contentView.addSubview(label)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// MARK: Main View Controller
class BlueViewController: UIViewController{
var tableView: UITableView!
var myDataSourse: MyTVDataSource!
var myDelegate: MyTVDelegate!

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
tableView = UITableView()
myDataSourse = MyTVDataSource(tableView: tableView)
myDelegate = MyTVDelegate()
myDelegate.presentingController = self
tableView.dataSource = myDataSourse
tableView.delegate = myDelegate
tableView.register(ItemCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(tableView)

self.tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0)
])
}
}
extension BlueViewController: BluePresenting{
func currentSelected(_ indexPath: IndexPath) {
print(indexPath)
}

}
// MARK: TableViewDelegate

protocol BluePresenting: class {
func currentSelected(_ indexPath: IndexPath)
}
class MyTVDelegate: NSObject,UITableViewDelegate{
var presentingController: BluePresenting?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
presentingController?.currentSelected(indexPath)
}
}
// MARK: TableView DataSource

class MyTVDataSource: NSObject, UITableViewDataSource{
private var tableView: UITableView
private var items = ["Item 1","item 2","item 3","Item 4"]
init(tableView: UITableView) {
self.tableView = tableView
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ItemCell(style: .default, reuseIdentifier: "Cell")
cell.label.text = items[indexPath.row]
return cell
}
}

是的,您可以将它们放在单独的类中。它们通常在同一类中,因为您可能需要在委托方法中使用数据(如数组(,如didSelectRowAtIndexPath

表视图和集合视图数据源和委托基于委托设计模式,您可以在其中将某些工作委派给其他对象。

为什么需要两种不同的协议?

因为数据源用于提供控制表视图/集合视图状态的数据,而委托提供行为并控制如何使用数据。

在某些特殊情况下,我将使用两个不同的类来实现delegatedataSource方法。

例如:

在我的项目中,一些数据由一个实例(我们称之为全局用户(包含 (,例如用户的文章,用户的评论,用户的产品...

在此类中,我对用户的数据有一些NSMutableArray,当用户登录成功时。 我从我的数据服务器请求他的数据并存储在这些数据数组中。

之后,当用户想查看他的产品时,他会点击一些类似my product的按钮,然后推送到MyProductListVC,在MyProductListVC中,我有一个tableViewinit来展示他的产品,但我不想再从我的数据服务器请求他的产品数据,因为我的所有产品数据都在我的全局用户类中,所以我把tableViewdataSource做到全局用户类,把delegate做到MyProductListVC,这个逻辑在我的项目中工作了很长时间。这就是我在不同类中定义委托和数据源的方式。

关于你的第二个问题:

Why we need seperation as delegates and datasources?

我根据我的项目回答了这个问题,首先,我希望所有用户的数据都集中在一个类上,这样方便我管理用户的数据。 其次,当我需要更改视图中数据显示的方式时,我只需要更改MyProductListVC中的代码即可。

以下是我认为最重要的:

我可以将所有请求方法放在我的全局用户的类中,我不希望我的MyProductListVC和任何其他 VC 中有太多的请求代码,因为在我的项目中,VC 只需要显示数据,不需要请求。

委派是子类的"替代品"。它采用适用于应用情况的通用行为。

数据源只是提供要显示的数据。

显然,有可能有两个视图具有相同的行为,但显示不同的数据。在这种情况下,为两个视图和两个不同的数据源设置一个委托很方便(而不是在每个数据源方法的开头都有ifs(。这意味着至少有一个视图的数据源不是其委托。

举个例子:您有一个显示球队球员的表格视图。还有一些额外的行为。你为此写一个委托。然后你有一个窗口,里面有两个视图,一个是主队,一个是客队。

这两个视图具有相同的行为适应委托和用于为玩家提供的不同数据源。

最新更新