Reputation: 4551
My UITableView
isn't showing any data. I think the problem is in:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell?`
This is my code:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
// Configure the cell...
let cellId: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellId) as UITableViewCell
if let ip = indexPath {
//var data: NSManagedObject = myList[ip.row] as NSManagedObject
//cell.textLabel.text = data.valueForKey("name") as String
cell.textLabel.text = "Hi"
}
return cell
}
I've seen tutorials on youtube that use this code, but I can't get it to work.
First I fought it was a problem with my array, but when i just put text in it it still doesn't show anything.
I'm running Xcode6 beta 3, but this code did run perfectly fine in beta 2.
I don't have any warning or error messages.
EDIT: I looked up some other Swift projects of me, I got the same function in there and it worked 2 weeks ago but now it also doesn't work. Maybe this is a Xcode6 beta 3 issue?
My class is of type UITableViewController
.
EDIT: I was looking through the Apple developer forums and saw related issues after updating to xCode 6 beta 3, so it's likely a problem with xCode 6 beta 3!
EDIT: The method doesn't get called.
Upvotes: 23
Views: 55121
Reputation: 4951
Apart from misspellings and syntax errors, there are some checks you have to do in order to make sure cellForRowAt will be called and your tableView
will be displayed properly:
dataSource
and delegate
Make sure to properly set the dataSource and delegate objects. Keep in mind that both of these variables are defined as weak
references. So they will not be retained. Make sure they do not get deallocated in the wrong place.
This is so rare, but still a possibility. here is an example:
Let's say you create a class to be your dataSource like this :
class MyDataSource: NSObject, UITableViewDataSource {
let list = ["Apple", "Google", "Microsoft", "Pinterest", "Amazon"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Create cell here
return UITableViewCell()
}
}
And then assign an instance of this class to your tableView's dataSource when creating it.
override func viewDidLoad() {
super.viewDidLoad()
let dataSource = MyDataSource()
let tableView = UITableView(frame: self.view.bounds)
tableView.dataSource = dataSource
tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(tableView)
}
Here Xcode wont complain but your dataSource object will be deallocated after viewDidLoad
has finished running, and because tableView does not retain dataSource object it will not call any of UITableViewDataSource function.
Register your cell class with proper cell identifier for your tableView
Make sure to implement numberOfRowsInSection
function and return the correct number of rows
The most important one which is indirectly mentioned in the accepted answer is to make sure that your tableView's frame is not zero. This can happen if you have conflicting constraints in Storyboard
or XIB
files that prevent AutoLayout
engine from correctly calculating the frame of your tableView or its cells. Or it can also happen when you define your tableView programmatically and forget to set the frame or layout constraints for it. UITableView
does not call dataSource functions in this case because it does not occupy any space on the screen. Unfortunately, this is not mentioned anywhere on Apple's documentation. However, you can test it yourself.
Upvotes: 0
Reputation: 276
I just ran into this problem as well. The cellForRowAt was not being called. And the Label inside the tableView kept indicating missing constraints everytime there was a change even after "add missing contraints" over and over again. In this case, the problem was that the tableView was inside a stackView. Once the tableView was relocated outside the stack, the tableView Label missing constraint errors stopped reappearing and the cellForRowAt operated correctly.
Upvotes: 0
Reputation: 702
In an interface builder, my screen is designed with table view as landscape mode and I am showing in real device as Portrait mode that is why cellForRow is not being called.
Now, solution for me is that I switched that screen from landscape to portrait in interface build and it worked.
Upvotes: 0
Reputation: 451
I had the same problem weird thing is Numbers of Rows method is getting called but cellForRowAtIndex is not getting called. In my case it is all due to the storyboard constraints and make sure tableiew is not hidden and is installed on the storyboard
Upvotes: 1
Reputation: 1
You need to set tableview
in editing mode in viewDidLoad
tableView.setEditing(true, animated: true)
Upvotes: 0
Reputation: 41
Make sure you hav setup delegate and datasource property for the UITableView object.
Upvotes: 0
Reputation: 1081
you need to set the height constraint for you table view. You can set in storyboard or programmatically. If you need then i will post a running example.
Upvotes: 0
Reputation: 156
Check if you have these lines:
tableView.delegate = self
tableView.dataSource = self
If dataSource = self
is not implemented it could be a reason of not called cellForRowAt indexPath
method
Upvotes: 7
Reputation: 2087
override func tableView(_ tableView: UITableView!,
cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { }
I was missing the underscore in as the first parameter tableView.
It also probably needed the override. You will know if you got the func described correctly if the override works.
Upvotes: 0
Reputation: 11276
I had the same frustrating issue when I migrated my old Swift 2.3 code developed in Xcode 8.2.1 to Swift 3.0 in Xcode 8.3, for me numberOfRows was getting called
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
but the main data source methods will never get called,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
The main issue was the UITableView I had created via Swift code was not added to any view, it was added but replaced by another view later so the data source method was never called. Hope it helps someone.
Upvotes: 0
Reputation: 409
Maybe you have declare delegate in init:
-(instancetype)init{
self = [super init];
if(self){
_tableView.delegate = self;
,...
}
return self;
}
Should be call it in ViewDidload:
- (void)viewDidLoad {
[super viewDidLoad];
_tableView.delegate = self;
,... }
Upvotes: 1
Reputation: 1828
Got it!
Had the same problem - I also have added a tableview into a uiviewcontroller and it also not worked, but I know the problem now.
If you add the tableview on interface builder AND click after that "Add Missing Constraints", it'll add constraints that can't work together.
At my position I had the tableview on my whole uiview and after click on "Add Missing Constraints", it will add this here:
And now if you delete one of the Trailing or Leading Alignments, it will work - cellforrowatindexPath will get called! Don't know why it is like that, but it will work.
Hope I can help you.
Upvotes: 62
Reputation: 671
XCode Version 6.3.1 (6D1002) I'm just run into this issue, In my case is I duplicate UITableViewController and reuse it somewhere cause this problem.
My solution is
Nothing to do with datasource btw, you can simply add some foo content to some label in cell to separated problem.
HTH
Upvotes: 1
Reputation: 126
May be this will help you.
I have the following:
self.myTableView.rowHeight = 60
in function heightForHeaderInSection: return 60
cellForRowAtIndexPath is not called
if a value >= 60 is returned in heightForHeaderInSection the cellForRowAtIndexPath is not called.
Even when I set self.myTableView.rowHeight = 59 (or 59 or 58), if I return in heightForHeaderInSection a value >= 60 the cellForRowAtIndexPath is not called.
So, I return a value <= 59 in function heightForHeaderInSection and the cellForRowAtIndexPath is then called. (use breakpoints in cellForRowAtIndexPath to check this).
Another issue: If cellForRowAtIndexPath is called but you don´t see the rows of your tableView: This is because the height of your tableView is too short.
For example: (in this case titulo_tabla is a UILabel that I have above my table. aOrdenes is an NSArray from which I get the count of rows that I show).
var width = self.view.frame.size.width
var height = self.view.frame.size.height
...
myTableView.frame = CGRectMake(width * 0.03, titulo_tabla.frame.origin.y + titulo_tabla.frame.height, width - 2 * (width * 0.03), 60.0 * CGFloat(aOrdenes.count) + 50)
In the last code, the last parameter ..., 60.0 * CGFloat(aOrdenes.count) + 50) the 60 is the rowHeight (self.myTableView.rowHeight = 60) and the 50 is the value returned in function heightForHeaderInSection. With this your tableView rows are showed.
Upvotes: 1
Reputation: 1
I was also having that problem on UITableView, I also set the data source and delegate to the table view but my cellForRowAtIndexPath
method was not called.
Solution:
my network blocked my method (by using firewall). I asked my network admin, and I was given full access to the network, and then my cellForRowIndexPath
method was called.
when my response comes from a web service, due to network block response was black so, cellForRowIndexPath
method was not called.
Upvotes: -3
Reputation: 4551
Seem's that there isn't a solution for this. Returned to xCode 6 beta 2 fixed the issue. Hopefully and likely it will get patched in Beta 4.
Upvotes: 1
Reputation: 154523
You need to implement this or cellForRowAtIndexPath
will never be called:
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
// Return the count of the number of rows in the table
return 5
}
The 5
is just an example of course. You would return the count of the number of elements in your array.
Upvotes: 12
Reputation: 1243
You must make sure that the datasource is correctly assigned and that you use the correct method signature. You declared some optionals wrong.
func tableView(tableView: UITableView!,
cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { }
Upvotes: 0