可能在不同的类中使用Delegate和Datasource吗? - UITableView

时间:2017-08-05 15:22:18

标签: ios objective-c swift uitableview delegates

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

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

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

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

4 个答案:

答案 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)

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

例如:

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

我为全局用户创建了一个实例类。在本课程中,当用户登录成功时,我有一些NSMutableArray用于用户的数据。 我从我的数据服务器请求他的数据并存储在这些数据数组中。

之后,当用户想要查看他的产品时,他会点击某个按钮,例如my product,然后推送到MyProductListVC,在MyProductListVC,我有一个{{1 init显示他的产品,但我不想再次从我的数据服务器请求他的产品数据,因为我在我的全局用户类中拥有他的所有产品数据,所以我做了tableView的{ {1}}到全局用户类,并tableViewdataSource,这个逻辑在我的项目上运行很长时间。这就是我如何在不同的类中定义委托和数据源。

关于你的第二个问题:

delegate

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

以下是我认为最重要的事情:

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

答案 3 :(得分:0)

委托是子类化的“替代”。它对您的应用情况采用通用行为。

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

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

举个例子:你有一个表格视图,显示一个团队的玩家。还有一些额外的行为。你为此写了一个代表。然后你有一个窗口,其中包含两个视图,一个用于主队,一个用于客队。

两个视图都有相同的行为调整委托和不同的数据源来提供玩家。