14

I'm learning swift, and the course I'm following teaches tableViews. It I have to set the TableViewController t include UITableViewDataSource and UITableViewDelegate. Then, in viewDidLoad, I have to set

tableView.dataSource = self
tableView.delegate = self

in order for the tableView to appear and load data.

Why do I have to do this?

Useful_Investigator
  • 938
  • 2
  • 8
  • 27
  • Possible dupe of :- http://stackoverflow.com/a/4213005/6297658 – Dravidian Aug 28 '16 at 07:27
  • A (subclass of) UITableViewController has dataSource and delegate already set to itself by default, compare http://stackoverflow.com/questions/34565570/conforming-to-uitableviewdelegate-and-uitableviewdatasource-in-swift. – Martin R Aug 28 '16 at 07:45

6 Answers6

25

Since you said you're learning Swift just thought of writing an elobrate answer. All the other answers already explains why you need to set the delegate to self or any instance of a class. But still I thought of writing this answer just to give more insight.

Let me explain what UITableViewDelegate & UITableViewDataSource are. Both UITableViewDelegate & UITableViewDataSource are protocols. What is a protocol? You can think protocol as a set of actions.

For example UITableViewDataSource has set of actions/methods like tableView(:numberOfRowsInSection:), tableView( tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) and so on.

What this protocol implies is that if you want to supply your custom data to the tableview, you need to conform to this protocol i.e. implement the non optional methods of the protocol(you can ignore optional methods if any).

Similarly, UITableViewDelegate has set of methods like, tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath), tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) and so on.

UITableViewDelegate protocol implies that you need to conform to the protocol if you want to get notified when user interactions happens at tableview for example when user taps on a cell of tableview.

So now, why are you setting

tableView.dataSource = self
tableView.delegate = self

is because you are implementing the protocols (or conforming to protocols )in your ViewController, TableViewDatasource protocol to supply your own data to the tableview, TableViewDelegate protocol to notify your ViewController class when user interacts with your tableview.

Actually you'll not be setting protocol conformance to self always, you can set it to instance of any class which implements the protocol.

Hope this Helps.

For more reference on protocols you can go through this: Swift 2 Tutorial Part 3: Tuples, Protocols, Delegates, and Table Views

iamyogish
  • 2,372
  • 2
  • 23
  • 40
7

You have to set a data source and a view delegate for the view to work. Those do not have to be self (i.e. the controller), it can be some other object (or two other objects, one data source and one view delegate).

It seems you implemented the methods for the two in your controller already, so it can act as all three (controller, data source, view delegate). But you still have to tell the view about it.

Thilo
  • 257,207
  • 101
  • 511
  • 656
4

I will provide in detail explanation for this. Here, UITableViewDataSource & UITableViewDelegate are actually protocols. Unfortunately, UIKit Framework is not open source. But I will assure you this is what internally happens after referring many articles.

Protocol is like basketball coach with some requirements in it. He/She tells players like class, struct, enum what to do? by using those requirements. But He/She doesn't knows how to do?by themself. So, the class or struct which conforms that protocol should provide implementation to those requirements while achieving to dunk the ball.

protocol UITableViewDelegate {
 func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
}

A Protocol is said to be DataSource protocol then it always contains required functions with "return type" as shown below.

protocol UITableViewDataSource {
 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
 func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
}

Implementing UITableView inside custom viewController

class viewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let tableView = UITableView()    

    override func viewDidLoad {
      tableView.delegate = self
      tableView.dataSource = self
    }

Here, tableView acts as Delegator(sender) & viewController object i.e (self) as Delegate(receiver).

UITableView() object now referred as tableView is having two optional stored property of respective protocol as type in UITableView() class & now it is called by tableView as

tableView.delegate: UITableViewDelegate?
tableView.dataSource: UITableViewDataSource?

In order to get UITableView in viewController.It should conform to both the Protocols. So, viewController class object has implemented all those required functions of both the protocols. Now self can be used either as UITableViewDelegate type or UITableViewDataSource type because Protocol can be used as type for an object of class which conforms to it. Now, both properties of tableView i.e delegate & dataSource are assigned to self because its having same respective protocol types.

The non-optional functions of both Protocols are implemented in viewController class object as below

Protocol UITableViewDelegate functions

func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
// Do further processes like pushing or poping another viewController
}

Protocol UITableViewDataSource functions

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
 }

func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
 }

1) When the user select a row in a section then tableview(Sender) i.e UItableView() calls the UITableViewDelegate func below shown by passing data to parameters tableView & indexPath which resides in viewController object(Receiver) through its delegate property. Now viewController uses those passed data to do further processes like pushing or poping to new custom viewController.

tableView.delegate?.tableView(UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

2) Functions inside UITableViewDatasource protocol provides custom data to tableview(Sender). The tableview asks the viewController object by calling Datasource functions with passing data to parameters tableView & indexPath which resides in viewController object(Receiver) through its datasource property. Now viewController uses those passed data & returns custom data back tableview. Now tableview uses those data to create "10" cells in a section & kind of "cell" at indexpath

tableView.dataSource?.tableView(UITableView, numberOfRowsInSection section: Int) -> returns "10"

tableView.dataSource?.tableView(UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> returns "cell"

So we assign both tableView.delegate & tableView.Datasource with self. Its not to conform for Protocol. But to initialise properties tableView.delegate & tableView.Datasource with self. So, that tableView can call those Delegate & Datasource methods residing in self through them.

A class is said to be conforming to protocol by just implementing all its requirements in it. Thats it but not by assigning self to properties of others.

Finally, whole UIKit Framework uses delegate & datasource design patterns in all its classes such as UIApplication, UITableView, UICollectionView, UITextField & so on to communicate data. Unfortunately, UIKit Framework is not open source.

Chethan M
  • 57
  • 5
2

Setting tableView.datasource = self means that the class this is called from will act as the tableView's data source provider, and has implemented functions to provide the tableView with data to fill in the tableView.

The same goes for delegate. The delegate (self) class has implemented functions that will be called when certain operations are done on the tableView, as clicking in a tableView's row.

Ivan C Myrvold
  • 680
  • 7
  • 23
2

Setting a delegate creates a connection between delegate object and your class. Delegate object handles the table view and lets your class know when its finished. By setting a delegate you can adjust behavior of tableview.

L.Kuchar
  • 56
  • 2
0

To deepen your understanding of DataSource and Delegate

Both Delegate and DataSource are types of a design pattern called Delegation Pattern which is commonly used in Apple FrameWork especially in UIKit.

The delegate pattern is used to communicate between two objects which one of them is responsible to delegate the task to another object. This pattern has three-part:

  1. Delegating object: which keeps a reference to the other object and it contains the protocol which allows you to call it when needed

  2. Delegate Protocol: which defines the method name of the delegate. (You have to know protocol before creating a delegate which will cover it on the next reference.

  3. Delegate: which is an object that implements the delegate method.

When you create a Delegating Object which is the tableView. The delegate protocol (UITableViewDelegate, UITableViewDataSource) is implemented to the Delegate, ViewController. Using UITableViewDelegate as an example, the delegating object detects a row that is selected and send a message to the delegate using the protocol method that is implemented which allows the delegate to response by changing it's state, appearance and etc. Therefore, the main value of delegation is that it allows you to customize the behaviour of serval objects in one central object.

You can go to https://appdevelopments.co/reference/designpattern/delegation for a better understanding.

Swee Kwang
  • 724
  • 9
  • 15