Code cracker
Code cracker

Reputation: 3166

Type 'ViewController' does not conform to protocol 'UITableViewDataSource'

Started practice swift. In singleViewController I am trying to make a UITableView. In storyboard I set the datasource and delegate. Here I am getting the error * 'ViewController' does not conform to protocol 'UITableViewDataSource' *

Screenshot for error

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var table: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

func numberOfSectionsInTableView(tableView: UITableView!) -> Int
{
    return 20
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
    let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
cell.textLabel.text="row#\(indexPath.row)"
    cell.detailTextLabel.text="subtitle#\(indexPath.row)"

    return cell

}

Upvotes: 52

Views: 91175

Answers (18)

islam XDeveloper
islam XDeveloper

Reputation: 500

just remove the viewDidLoad() and Build and add viewDidLoad() everything is ok

Upvotes: 0

iDevSpread
iDevSpread

Reputation: 301

In general, a protocol has optional and required methods. For example, UISearchBarDelegate and UITableViewDelegate are the cases that you can declare to conform to a protocol without implementing any of their methods. But it does not work fine for UITableViewDataSource.

In the official documentation, Protocol "UITableViewDataSource" -> Symbols -> Configuring a Table View, the methods: func tableView(UITableView, cellForRowAt: IndexPath) and func tableView(UITableView, numberOfRowsInSection: Int) shown with bold Required key word.

Upvotes: 0

Nilo0f4r
Nilo0f4r

Reputation: 168

with some edits suggested by auto complete, from the above answer by @MB_iOSDeveloper on swift 3, Xcode 8.3.2, this code works for me:

class MenuViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

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

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    //currently only a testing number
    return 25
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{

    var cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "mycell")
    cell.textLabel?.text = "row#\(indexPath.row)"
    cell.detailTextLabel?.text = "subtitle#\(indexPath.row)"
    return cell
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Upvotes: 0

yash yadav
yash yadav

Reputation: 3

Copy the code below under the ViewController class and specify the number of rows you want (in the 1st section) and define the content of each cell (in 2nd function)

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {


public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 1        //no. of rows in the section

}

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell  {

    let cell = UITableViewCell(style: <#T##UITableViewCellStyle#>, reuseIdentifier: <#T##String?#>)

}




override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Upvotes: 0

Jothi Karunagaran
Jothi Karunagaran

Reputation: 69

Add these methods

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
}

Upvotes: 0

Sanju
Sanju

Reputation: 1168

Just Add these two methods then that error will be resolved[XCode8 Swift3]

first method :

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

Second Method :

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
}

Upvotes: 2

waseefakhtar
waseefakhtar

Reputation: 1423

The answer of Ankit worked for me in Xcode 8 for Swift 2.3. Here’s the new syntax.

extension ViewController: UITableViewDataSource {
    internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //return 1
    }

    internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //return cell
    }
}

Upvotes: 0

Ankit
Ankit

Reputation: 141

Change the syntax of "UITableViewDataSource" protocol required methods as per new swift 3 documentation:

internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int

internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

This has worked for me while compiling with swift 3 compiler

Upvotes: 0

KawaiKx
KawaiKx

Reputation: 9918

This is a common warning which means that " you haven't implemented the required methods of the protocol yet"

A view object on the storyboard may need a datasource. For example, TableView needs a datasource and usually, View Controller acts as one.

So Table View expects the ViewController to contain the methods which return the 'must have' information for the table view.

Table view needs to know the number of sections, number of rows in each section etc..

Unless all the required information is returned by the datasource object, the warning will persist.

Upvotes: 0

Yunus Nedim Mehel
Yunus Nedim Mehel

Reputation: 12369

This is probably caused by a typo or wrong styling on the method name. I used to cmd + left click on UITableView and copy & paste method names on my UIViewController; which won't work on Swift.

Instead, type func tableView, look for the desired method on the list and let auto complete do its job.

Autocomplete

Upvotes: 0

Yuting
Yuting

Reputation: 131

I had just faced the same problem in Swift.

You should realize all the functions for the UITableViewDataSource in the class, which means the following functions should be realized:

func numberOfSectionsInTableView(tableView: UITableView) -> Int{}

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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {}

I'm not sure whether missing the function for numberOfSectionsInTableView works for you or not. For me, I have to realize it in my class.

Upvotes: 2

Valentin
Valentin

Reputation: 3302

Just a suggestion to improve readability, you can separate your protocols using extension, like this:

class ViewController: UIViewController {
    // Your lifecycle code here
}

extension ViewController: UITableDataSource { 
    func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
         return 20
    }
}

extension ViewController: UITableViewDelegate {
    ...
}

Upvotes: 0

MB_iOSDeveloper
MB_iOSDeveloper

Reputation: 4198

The following code didn't work for me on iOS 8.1. in XCode 6.1.1. This code works:

import UIKit

class ViewController : UIViewController,UITableViewDelegate,UITableViewDataSource {

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

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        //currently only a testing number
        return 25
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

        var cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
        cell.textLabel?.text = "row#\(indexPath.row)"
        cell.detailTextLabel?.text = "subtitle#\(indexPath.row)"
        return cell
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Upvotes: 2

ShaluRaj
ShaluRaj

Reputation: 67

Take out all the optionals for tableview and NSIndexpath for the latest Xcode 6.1.1 GM_Seed

Upvotes: 0

Muhammad Umar
Muhammad Umar

Reputation: 151

I had the same problem, things would workout rather easily in Objective-C, probably because we are more familiar with it at the moment, but in this case, swift is very new, therefore, the its error notifications are rather vague.

While I was implementing the UITableView based application, and I ran into this problem. I opened up the implementation file for UITableView by pressing command and clicking on UITableView. In implementation file, we can clearly see that two functions are mandatory to implement,

  1. func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
  2. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

I arrived at this post and started to put things together while keeping my meager knowledge of objective-C programming in mind. Reason for the error being that a table view is defined by two elements, first the section and rows in a section, and second the tableview cells. By default there is at least one section in the table view, but we need conformance about number of rows in a section. Secondly, we need to know which cell are we going to present in a particular row in a section. Regardless,even if we are using default UITableViewCell, we still need an identifier to access it in order to set its subviews or properties. I hope it was helpful, A bit soft criticism will be appreciated since I am myself very new to Swift :)

Upvotes: 4

aalesano
aalesano

Reputation: 357

Try removing the ! on your func. That did the job for me

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
    cell.textLabel.text="row#\(indexPath.row)"
    cell.detailTextLabel.text="subtitle#\(indexPath.row)"

    return cell
}

Upvotes: 16

user3732709
user3732709

Reputation:

You should implement all the required methods before the last }, but you have written them outside of the UIViewController. Also, you need to change the func for number of lines.

the suggested edit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var table: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int
    {
        return 20
    }

    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
        cell.textLabel.text="row#\(indexPath.row)"
        cell.detailTextLabel.text="subtitle#\(indexPath.row)"

        return cell
    }
}

Upvotes: 75

staticVoidMan
staticVoidMan

Reputation: 20234

You need to implement all the required methods of UITableViewDataSource in order to get rid of that error.

Basically... you're missing:

func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
    //return XX
}

Upvotes: 10

Related Questions