Delegate and Datasource in different classes possible? - UITableView
Asked Answered
P

4

10

While using UITableView there are two types of methods ie, datasource and delegates still both supposed to be connected to the same parent view controller class.

Is there any way to define delegates and datasources in diffrent classes?

Why we need seperation as delegates and datasources?

Note: This question applies to UICollectionView and similar Objects

Pennant answered 5/8, 2017 at 15:22 Comment(1)
Answer in one word, YES.Curfew
C
6

As explained well enough about the delegation pattern in other responses, we can declare tableview Datasource and Delegate as different objects in order to avoid Massive ViewControllers and to achieve lean ViewControllers .

Here is a code example Using Delegate Design pattern .

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
    }

}
Crisper answered 24/6, 2018 at 9:38 Comment(0)
C
4

Yes you can have them in separate classes. They are normally in the same class because you may need to use data(like array) inside delegate methods like in didSelectRowAtIndexPath:

Tableview and Collectionview Datasource and Delegates are based on Delegate design pattern, where you can delegate some work to other objects.

Why do you need two different protocols?

Because datasource is used to provide data that controls the state of the tableview/collectionview whereas delegate supplies behaviour and controls how to use the data.

Circumfluous answered 5/8, 2017 at 15:32 Comment(6)
How it is possible because my tableview is contained inside a viewcontroller only. which classes i do want to use?Pennant
your tableview is inside view controller and it has exposed two delegate properties(different protocols), where you can pass any class(object) conforming those protocols.Circumfluous
@Saranjith: Have edited the answer. I hope I am able to understand your question and answer it.Circumfluous
Is it possible if i define datasources in uitableview class and delegates in my uiviewcontroller class?Pennant
@Saranjith: Much more common that you define datasource in a completely different class that has nothing to do with the tableview, but focuses exclusively on providing the data.Electrodeposit
@Pennant : If you want to define datasource in uitableview subclass, you can ofcourse do it but ideally you would want to separate your view and data classes. The whole point of using delegates are to separate responsibilities.Circumfluous
V
0

in some Special Situation, i will use two different class to realize the delegate and the dataSource method.

for example:

in my project, some data contain by a instance(let's call it Global user ), such as user's article, user's comment, user's product...

i make a instance Class for the Global user. in this class , i have some NSMutableArray for user's data,when user login success. i request his data from my data server and store in these data Array.

After that, when the user want to look his product, he will click some button like my product, then push to MyProductListVC, in the MyProductListVC, i have a tableView init to show his products, but i don't want to request his products data from my data server again, because i have all his product data in my Global user Class,so i make the tableView's dataSource to the Global user class, and make the delegate to the MyProductListVC, and this logic works fine on my project for a long time. this is how i define delegates and datasources in diffrent classes.

About your second question:

Why we need seperation as delegates and datasources?

i answered this question based on my project, first ,i want all user's data focus on one Class, this way convenient for me to manage the user's data. second , when i need to change how show the data in the view, i only need to change the code in MyProductListVC.

Here's what I think is the most important:

i can put all request method in my Global user's Class, i don't want too many request code in my MyProductListVC and any other VC, because in my project, the VC only need to show data, don't need to request.

Vesica answered 6/8, 2017 at 2:45 Comment(4)
what is base class of your global class?Pennant
NSObject classCutis
you can define datasources in uitableview class, but i won't do this, because i don't think put the request data method into uitableview class is a good idea.Cutis
my global class is a singleinstance, so when i use it, it's already Initialization completed, if you want use uitableview as the datasource, you must be sure your uitableview when you use was Initialization completed. otherwise, you will receive a warning or a error.Cutis
I
0

Delegation is a "replacement" for subclassing. It adopts the generic behavior to your app situation.

Data sources simply provides the data to be displayed.

Obviously it is possible to have the case, that two views have the same behavior, but display different data. In such a case it is convenient to have one delegate for both views and two different data sources (instead of having ifs at the beginning of every data source method). This implies that at least one view has a data source that is not its delegate.

To have an example: You have a table view displaying players of a team. There is some extra behavior. You write a delegate for this. Then you have a window with two of that views, one for the home team, one for the away team.

Both views have the same delegate for behavior adaption and different data sources for providing the players.

Intrench answered 6/8, 2017 at 7:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.