Conforming to UITableViewDelegate and UITableViewDatasource in Swift?
First of all, that is completely independent of which language
you use, Swift or Objective-C.
But there are two different cases which may cause the confusion:
A UITableViewController
subclass:
UITableViewController
already conforms to UITableViewDataSource
and UITableViewDelegate
. It has a tableView
property,
whose dataSource
and delegate
property are already set to self
.
In your subclass, you typically override the
data source and delegate methods.
A UIViewController
subclass with a UITableView
property:
Here you have defined a UITableView
property in your subclass
and initialize it in your code, or
connect it to a table view in the interface builder.
In this case you have to set the dataSource
and delegate
property of the tableview, either in code or in the interface
builder, as explained in luk2302's answer.
If data source and delegate are the view controller itself,
then you have to declare the protocol conformance explicitly,
and implement the
data source and delegate methods (but without overriding
a superclass method).
Of course, in both cases, the table view data source and the delegate
can be set to a different object, it does not have to be
the view controller itself.
Can ViewModel class conforms to UITableviewDelegate and UITableViewDataSource in iOS as per MVVM
Yes you can, set any object that conforms to those protocols as the delegate, data source or separate them to different objects, anything and anyone can implement a protocol.
When writing a complex table view data source or delegate, It’s better to define a type whose purpose is to be a table view’s data source. This helps to better separate responsibilities between objects.
You can find an example by Apple implementing different objects as the table/collection View's data source here:
Advanced User Interfaces with Collection Views by apple
These object/s doesn't have to be your viewModel, but please see a good example when it is:
MVVM with viewModel as the table datasource
UITableView does not conform to protocol UITableViewDataSource error
You have incorrectly set up your ViewController. Either create a UITableViewController which is just a UITableView, or add a UITableView to a UIViewController (Like you have almost done).
The didSelectRowAt method will allow you to segue to a new viewController, but in my examples only if it is set up correctly in a storyboard.
UITableViewController option
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
// MARK: - Table view delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
performSegue(withIdentifier: "SegueIdentifier", sender: self)
}
UIViewController option
(The UITableView will need to be added through a Storyboard in this example)
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
// MARK: - Table view delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
performSegue(withIdentifier: "SegueIdentifier", sender: self)
}
Here is an example project to work from
Why do I have to set the dataSource and delegate to self?
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
Does Not Conform To Protocol 'UITableViewDataSource' Error?
If you start typing the name of the functions Xcode will auto-complete them for you. Here's an example that'll help you. (And doc. in the link)
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
UITableView delegate using extensions swift
You can divide in a extension, as you can check in the apple documentation section about Extensions handling Protocols.
Here I have implement a minimum code doing what you ask, check it out.
import UIKit
class TableViewViewController: UIViewController {
@IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
}
}
extension TableViewViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel!.text = "it works"
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
}
swift protocol with uitableviewdatasource
If you want to implement these data source methods and reuse them, just define a data source class that implements them. And then rather than implementing the delegate methods in the view controller, instantiate a data source object, keep a strong reference to it, and specify it as the data source for the table view.
For example:
class DataSource: NSObject, UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// configure cell here
return cell
}
}
class ViewController: UITableViewController {
let dataSource = DataSource()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = dataSource
}
}
ViewController' does not conform to protocol 'UITableViewDataSource' swift
The problem is that you are using lower version of swift
not swift 3.0
, method cellForRowAt indexPath
is work with swift 3.0, so you need to use this cellForRowAtIndexPath
instead of that.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MenuCell", forIndexPath: indexPath) as! MenuCell
if (indexPath as NSIndexPath).row < itemsArray.count {
let option = itemsArray[(indexPath as NSIndexPath).row]
cell.titleLabel?.text = option
}
return cell
}
Related Topics
Swift: Iboutlets Are Nil in Custom Cell
Perform "Use Photo" Button on Custom Image Picker Overlay
How to Fix Broken Transform-Origin on iOS11 and Macos10.12 Safari
How to Get Nsnumberformatter Currency Style from Isocurrencycodes
How to Programmatically Delete My Own iOS App
Selecting All The Items in UIcollectionview iOS, Even The Cells That Are Not Visible
Ckfetchnotificationchangesoperation Sometimes Does Not Return Update, Delete Notifications
How to Fetch Images from Photo Library Within Range of Two Dates in iOS
iOS 8 Uitableview First Row Has Wrong Height
How to Animate a Nslayoutconstraint in Swift
Objc Protocol Implementation in Swift
Can Push Notifications Be Used to Run Code Without Notifying User
Dateformatter Gives Wrong Time on Conversation
Why Use Corebluetooth Connectperipheral Did Not Call Delegate Methods in iOS8
How to Show Viewcontroller from a Non-Viewcontroller Helper Class