I get this error message: failed to obtain a cell from its dataSource
The strange that
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
not even get called, problem is not that returned cell is nil. I put in breakpoints. cellForRowAtnot get called.
numberOfRowsInSection returns value.
I do not know it is relating or not, but now I do not use UITableViewController, I just have a UIViewController, and it is the datasource and delegate for the UITableView. I hope it can not cause interfere. Any idea?
Cross check below check list:-
it's because you are failing to dequeue a reusable cell.
The problem is that your cellForRowAtIndexPath function is embedded in another function
when you forgot to add the UITableViewDataSource and UITableViewDelegate protocols to the ViewController declaration.
class DataViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
I guess this is your problem - Failed to obtain a cell from its DataSource
you can take a look at: https://www.hackingwithswift.com/example-code/uikit/fixing-failed-to-obtain-a-cell-from-its-datasource
try something like this:
cell = tableView.dequeueReusableCellWithIdentifier(getCellIdentifierForType(cellType))
setDataToCell(cell, item: item)
good luck
Please make sure when you are migrating your code from swift older to new versions then your tableview data source and delegates have updated syntax.
For example
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
and
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
Can not auto updated to below:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
Related
I just upgraded my codes to Swift 4 and now receiving this warning on console for all tableView function.
tableView:willDisplayCell:forRowAtIndexPath:] is deprecated and will be removed in Swift 4; add explicit '#objc' to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message
tableView:cellForRowAtIndexPath:] is deprecated and will be removed in Swift 4
Use below code for cellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
Use below one to identify cells which are displaying
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
}
if you have doubt regarding datasource and delegate function select UITableViewDataSource or UITableViewDelegate and right click jump to definition that will lead to get your functions
Hope this will help you
I'm not recommend anone to fix this problem like this but it did worked for me.
You could add "#objc" at the beginning of every tableView function You use.
Like this:
#objc func tableView(_ tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return 1
}
I have a CoreData entity which I need to populate the value of each objects into a table view cell. In the storyboard, I can add rows and change the style of my cells individually, but in this case I'm dealing with cells based on my number of objects and I have to programmatically insert rows and change the cell style.
I'm guessing that I need a foreach loop with the code to insert rows programmatically. Does anyone know how to achieve this?
You have to implement UITableViewDataSource. See the API Reference for more information.
When using Core Data with UITableViews you might also want to take a look at NSFetchedResultsController.
You need to use UITableViewDataSource methods. Add the dataSource protocol to your class and conform to it. The method you are looking for is:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
You probably will also want to conform to UITableViewDelegate protocol.
Do something like this:
class MyClass: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Do your thing
}
//Conform to rest of the delegate and datasource methods too. Click on UITableViewDataSource to see the documentation
You need to implement override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int and return your objects array's count, then set a reuse identifier for the cell and add the code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") //replace "Cell" with your identifier
cell.textLabel = yourTitleArray[indexPath.row]
cell.detailTextLabel = yourSubtitleArray[indexPath.row]
return cell!
}
Don't forget to replace yourTitleArray and yourSubtitleArray with your arrays.
I have updated my code to swift 3.0 and get a warning on the following line:
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
When I try each of the suggestions to either silence the warning with #nonobjc or make it a private function the table no longer loads.
The error reads:
Instance method 'tableView(:cellForRowAtIndexPath:)' nearly matches optional requirement 'tableView(:canFocusRowAt:)' of protocol 'UITableViewDelegate'
Does anyone know what causes this error and how to fix it?
Many thanks!
Just add the declaration of implementing UITableViewDataSource protocol to the class definition like this:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {}
In swift 3.0 the signature for the datasource changed to:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
Notice the difference between cellForRowAtIndexPath indexPath: IndexPath and cellForRowAt indexPath: IndexPath
I'm using the new method without any warnings, hope this will solve your problem.
Cheers.
I had a similar problem, and found that if you remove the space between the underscore before tableView, from this
func tableView(_ tableView: ...
to this
func tableView(_tableView: ...
strangely the warning goes away...
I have some questions with Swift 3 function calling. Below is an example.
Old Swift:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell
Swift 3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
That's fine with the above syntax. But now Xcode shows me an error and asks me to do like below:
#objc(tableView:cellForRowAtIndexPath:) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
I do not understand why I have to declare #objc(tableView:cellForRowAtIndexPath:).
This is happening only when I am trying to implement table view datasource methods under an extension. Also this is not happening for numberOfRowsInSection or viewForHeaderInSection.
Can anyone help me to understand why this is happening?
While I am not sure what triggers the #objc, I can suggest the following approach:
Store the tableView variable somewhere in the viewDidLoad:
let tv = tableView!
Then hover over the tableView variable and press the command button in conjunction with a click.
This should take you to the interface of a UITableView.
Then, hover over either UITableViewDelegate or UITableViewDataSource and press the command button in conjunction with a click.
Now you can see the new signatures.
A lot has changed...Happy upgrade!
Swift compiler forced to write Objc(funcName) before function if you are using this function from Objective c. According to app doc
Use the #objc(name) attribute to provide Objective-C names for
properties and methods when necessary. For example, you can mark a
property called enabled to have a getter named isEnabled in
Objective-C like this:
var enabled: Bool {
#objc(isEnabled) get {
// ...
}
}
To void this, use extension to write TableView Datasource and delegate
extension YourViewControllerName:UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell() as SplitAddContactCell
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80.0
}
}
i am fresher and i am doing my app in swift language and i want to know that what is the difference between
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?
and
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell/
delegate methods in UITableView?
As a one line answer to the question,
The first method
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?
is not tableView delegate method. It an instance method in UITableView Class. Which is used to get a cell from tableView instance by passing indexPath as parameter. So you will be using this method on a tableView instance.
The second method
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
is the datasource method of UITableView that is used to populate tableview cells. This method will be implemented in the datasource/delegate class.
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? is a UITableView method, it is used to get a cell at a given time when the tableview is defined. For instance, it can be used to check is a cell is visible. If it is not visible this method will return nil.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell is a UITableViewDataSource method, it is used to define all the cells of the tableview, so that it can know what to display.
The first method
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?
It is an instance method in UITableView Class. And it is used to get a cell from tableView instance by passing indexPath as parameter .
and the second one
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
is the datasource method of UITableView and it is one of the require method in UITableView.
Thank you.