Vlad Markushin Vlad Markushin - 2 months ago 20
Swift Question

Swift - UITableView doesn't work with delegates

The problem is that

UITableView.dataSource
works fine with extensions, but does not work with delegates.
I created new project and added just one
UITableView
to the storyboard.

Here is the code using extension:

import UIKit

class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
// tableView.dataSource = Delegate()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

extension ViewController: UITableViewDataSource {
//class Delegate: NSObject, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(1) // called several times
return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(2) // called

var cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "UITableViewCell")
}
return cell!
}
}


Using delegate:

import UIKit

class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
// tableView.dataSource = self
tableView.dataSource = Delegate()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

//extension ViewController: UITableViewDataSource {
class Delegate: NSObject, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(1) // called several times
return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(2) // doesn't called

var cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "UITableViewCell")
}
return cell!
}
}


Has anyone encountered such a problem?

Answer Source

You need to store your Delegate object in you view controller. The reason for this is that dataSource variable of UITableView is a weak variable (so as to prevent retain cycles) - it means that if it isn't stored somewhere in a strong variable, it will immediately get deallocated.

tableView.dataSource = Delegate()

Here you assign new instance of Delegate to a weak variable and nowhere else. Do something like this

class ViewController: UIViewController {
    var delegate = Delegate()

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self.delegate
}