使用UITableView时,有两种类型的方法,即数据源和委托仍然应该连接到同一父视图控制器类。
有没有办法在不同的类中定义委托和数据源?
为什么我们需要分离作为代理和数据源?
注意:此问题适用于UICollectionView和类似的对象
答案 0 :(得分:4)
是的,你可以将它们放在不同的课程中。它们通常位于同一个类中,因为您可能需要在didSelectRowAtIndexPath
中的委托方法中使用数据(如数组):
Tableview和Collectionview数据源和代理基于Delegate design pattern,您可以在其中将某些工作委托给其他对象。
为什么需要两种不同的协议?
因为数据源用于提供控制tableview / collectionview状态的数据,而委托提供行为并控制如何使用数据。
答案 1 :(得分:3)
正如在其他响应中对委托模式所做的充分解释一样,我们可以将tableview数据源和Delegate声明为不同的对象,从而避免使用大量的ViewController并实现精益的ViewController。
这里是使用Delegate Design模式的代码示例。
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
}
}
答案 2 :(得分:0)
在某些特殊情况下,我将使用两个不同的类来实现delegate
和dataSource
方法。
例如:
在我的项目中,一些数据包含一个实例(让我们称之为全局用户 ),例如用户的文章,用户的评论,用户的产品......
我为全局用户创建了一个实例类。在本课程中,当用户登录成功时,我有一些NSMutableArray
用于用户的数据。
我从我的数据服务器请求他的数据并存储在这些数据数组中。
之后,当用户想要查看他的产品时,他会点击某个按钮,例如my product
,然后推送到MyProductListVC
,在MyProductListVC
,我有一个{{1 init显示他的产品,但我不想再次从我的数据服务器请求他的产品数据,因为我在我的全局用户类中拥有他的所有产品数据,所以我做了tableView
的{ {1}}到全局用户类,并tableView
到dataSource
,这个逻辑在我的项目上运行很长时间。这就是我如何在不同的类中定义委托和数据源。
关于你的第二个问题:
delegate
我根据我的项目回答了这个问题,首先,我希望所有用户的数据都集中在一个类上,这样便于我管理用户的数据。第二,当我需要更改在视图中显示数据的方式时,我只需要更改MyProductListVC
中的代码。
以下是我认为最重要的事情:
我可以将所有请求方法放在我的全局用户的类中,我不希望在我的Why we need seperation as delegates and datasources?
和任何其他VC中有太多请求代码,因为在我的项目中,VC只需要显示数据,不要不需要请求。
答案 3 :(得分:0)
委托是子类化的“替代”。它对您的应用情况采用通用行为。
数据源只提供要显示的数据。
显然有可能有两个视图具有相同行为但显示不同数据的情况。在这种情况下,为两个视图和两个不同的数据源设置一个委托是很方便的(而不是在每个数据源方法的开头都有if
s)。这意味着至少有一个视图的数据源不是其委托。
举个例子:你有一个表格视图,显示一个团队的玩家。还有一些额外的行为。你为此写了一个代表。然后你有一个窗口,其中包含两个视图,一个用于主队,一个用于客队。
两个视图都有相同的行为调整委托和不同的数据源来提供玩家。