I want to load around 6000 - 8000 rows in a UITableview. I get the data from the server using a async call and when I get the data I call
[tableView reloadData]
This is to refresh the table view . But because of some reason my app gets stuck and freezes .
When I debug , I found that cellforrowatindexpath is called 6000 times (on main thread) and
dequeueReusableCellWithIdentifier always returns null .
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CDTableRowCell *cell = nil;
// Create and Resue Custom ViewCell
static NSString *CellIdentifier = #"CellIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// got into render/theme objec
if(cell == nil){
cell = [[CDTableRowCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// MODIFYING CELL PROPERTIES HERE FROM AN ARRAY
// NO HTTP CALLS
}
Also, tableview starts reusing cell once I start scrolling but before that I never always create a new one.
Any clue why this strange behavior ???
try like this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier =#"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
The method in your question is not a table view datasource method. The datasource method has the table view as an argument. The method you have written is one that can be used to obtain a cell from the tableView itself, not to obtain a new cell from the datasource.
I don't know how often that method is called but overriding it is almost certainly not what you want to do.
I'm guessing you have subclassed a uitableview to be its own datasource? If so, you need to have the code in your question in the datasource method tableView:cellForRowAtIndexPath:, and not override the method as you have now.
Related
I am using a custom cell class in a tableview controller.
When I include a statement in the tableviewcontroller in cellForRowAtIndexPath NSLog(#"method called"): it does not seem to get called.
Is it possible that this method is not called when you have a custom cell?
Edit:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell for row at index path called");
NSDictionary *item= [self.getItems objectAtIndex:indexPath.row];
//This sets place in storyboard VC
IDTVCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.item = item;
if (cell == nil) {
cell = [[IDTVCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
return cell;
}
cellForRowAtIndexPath is not called if no rows are returned.
-tableView:cellForRowAtIndexPath: is not getting called
That is what happened in my case.
It can also not get returned if you reload table on wrong thread and in certain other scenarios.
cellForRowAtIndexPath: not called
However, a custom cell per se does not cause this..
To answer your question - Yes, it is.
There could be n-number of reasons why cellForRowAtIndexPath: is not getting called. This may be because delegate / dataSource is not set or UITableView frame is not set... etc. etc.
You should easily find a solution with more online research and closure look at your code.
I have a custom UITableView class that I have multiple instances of in a single ViewController. What is the most elegant way to populate these different instances with unique cell data? Thanks for any help in advance!
Right now I can think of two possible solutions:
Have different table view data sources for each table. You can create the data sources in the same file as the view controller if that is important to you.
Have your tableView:cellForRowAtIndexPath: method conditionally load the cells depending on the table. You can find out which table view is calling the method with the first argument of the method. You could also use the tag property of UITableView for differentiation.
I personally prefer the first one.
The answer I wrote here:
https://stackoverflow.com/a/19568737/480415
May help you achieve this.:
You could also put 2 separate UITableViews on your UIViewController,
then handle it in the delegates/datasource methods, ie:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView == _leftTableView)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//fill cell data here
return cell;
}
else if(tableView == _rightTableView)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//fill cell data here
return cell;
}
return nil;
}
Notice that the method signature tableView:cellForRowAtIndexPath: includes a reference to the tableView. You can use that to determine which tableView is requesting a cell, and return the same/different data accordingly.
in your controller, you should have your tableViews defined as a properties
#property (nonatomic, strong) UITableView *myTableView
Then, in tableView:cellForRowAtIndexPath: you can check which table is making the callback using something like:
if (tableView == self.myTableView){
//return cell
} else if (tableView == someOtherTableView) {
//return some other cell
}
I'm using ARC but it seems that my custom UITableCellView is not release.
TBMListingLineView is a subclass of TBMGlobalCustomCell which is a subclass of UITableCellView.
In TBMListingLineView there are 10 UILabels (nonatomic, retain)
I've implemented in both classes the method dealloc which is never called (breakpoint doesn't stop the execution)
When I'm scrolling the TableView, the number of UILabel is increasing in Instruments/Allocations and that causes the application crashed after several memory warning.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = #"Cell";
TBMGlobalCustomCell* cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
switch(sortIndex) {
case 0 :
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil || ![cell isKindOfClass:[TBMListingLineView class]]) {
cell = [[TBMListingLineView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
break;
....
return cell;
}
The first problem is that you call dequeueReusableCellWithIdentifier twice for each cell.
And then you "throw away" the second dequeued cell also if it does not have the right class.
A better solution is to use different cell identifiers for each cell (sub)class used in
the table view, so that dequeueReusableCellWithIdentifier returns instances of the correct
class.
I'm doing a simples app using Storyboard that a have a View with a UITableView with a UITableViewCell that do the navigation to another UIView.
So a have to code to populate the cell on the table view.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"SampleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
NSLog(#"cai no init da cell");
}
GPItem *item = [self.items objectAtIndex:indexPath.row];
cell.textLabel.text = #"Post";
cell.detailTextLabel.text = item.imageURL;
return cell;
}
I realised that the code if (cell == nil) { ... never executes so I really need to do that on uses the cell from Storyboard?
Thanks.
You are correct; that code is guaranteed to return a non-nil cell if you are using a storyboard. Also, in iOS 6, the new call dequeueReusableCellWithIdentifier:forIndexPath: never returns nil. See the discussion in my book:
http://www.apeth.com/iOSBook/ch21.html#_registering_a_cell_class
If you've declared your UITableViewCell in table view's prototype cells it's already allocated and just needs to be dequeued. If you're using a custom UITableViewCell subclass, then you must check if it's nil and allocate new entities when necessary.
Nope you don't need that code when using a cell made in your storyboard.
It is probably best to remove this code so that you crash nice and early if the identifier you gave to the cell in interface builder and the identifier you use in code ever drift. This snippet will mask this error and just provide a cell that you most likely was not intending to have.
I'm using the table view in the view controller, with the simple array was displayed in the list. That array was displays and works fine but I'm getting this warning. May I know the reason for this and please some ideas to rectify this issues..
WARNING: Using legacy cell layout due to delegate implementation of
tableView:accessoryTypeForRowWithIndexPath: in . Please remove your implementation of this method and set
the cell properties accessoryType and/or editingAccessoryType to move
to the new cell layout behavior. This method will no longer be called
in a future release.
Thanks
The method tableView:accessoryTypeForRowWithIndexPath: is deprecated in iPhone OS 3.0. Delete the implementation of this method and add the following code in the method cellForRowAtIndexPath: :
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
See UITableViewCellAccessoryType in the documentation for other type.
Im using the following code as you mentioned :
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
cell.text = [arry objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
But it returns the same
Its just saying that this method is about to disappear in next version, so you should go to documentations look for tableView:accessoryTypeForRowWithIndexPath and surely you will find alternative ways of doing what you want you want to do.
In other words, set the accessory of that cell by calling UITableViewCell accessory-view and accessory-type properties
myCell.accessoryType = ...
myCell.accessoryView = ...