reloadData not working - suspect cell's reuseIdentifier - iphone

I have a view controller that gets presented modally and changes some data that effects the data in a uitableview in the modal's parent view controller (a table view).
I call the tableview's reloadData method when the parent view reappears. I have confirmed that this code gets hit with a break point. My trouble is, reloadData isn't working. Here's the kicker - if I don't use reuseIdentifiers in the - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath method, the data reloads correctly. It looks like the reuseIdentifier is to blame.
I really want to continue to use the reuseIdentifier for my cells - how do I make this work?

Got it figured, and you're right, it's not the reuseIdentifer.
I was nesting the content assignment right below the cell allocation like so:
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = [targetRow.children count] ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
// Configure the cell.
cell.textLabel.text = [NSString stringWithFormat: targetRow.title];
}
Since the dequeued cell was found, the content wouldn't get updated.
I changed it to this and all works great now...
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.accessoryType = [targetRow.children count] ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
// Configure the cell.
cell.textLabel.text = [NSString stringWithFormat: targetRow.title];

The problem is unlikely to do with the reuse identifier. Please post your code for your tableView:cellForRowAtIndexPath: method.

Related

Slider gets reload in Table View in Iphone SDK

In my app, i add a slider in Table view i.e. each row contains a slider & It also works fine.
But when i scroll the table view the slider get reload i.e. each shows me starting position rather than slider value.
//My code is as follow for slider in table cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier=[NSString stringWithFormat:#"CellIdentifier%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
return cell;
}
UISlider* theSlider = [[[UISlider alloc] initWithFrame:CGRectMake(174,12,120,23)] autorelease];
theSlider.maximumValue=99;
theSlider.minimumValue=0;
[cell addSubview:theSlider];
return cell;
}
How can i solve this??
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier=[NSString stringWithFormat:#"CellIdentifier%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; UISlider* theSlider = [[[UISlider alloc] initWithFrame:CGRectMake(174,12,120,23)] autorelease];
theSlider.maximumValue=99;
theSlider.minimumValue=0;
[cell addSubview:theSlider];
} return cell;
This way the slider gets created only when cell is nil i.e cell gets created. and use tableView:willDisplayCell:forRowAtIndexPath: method to set the slider value like slider.value = yourvalue;
You need to store values of slider view and set the values of sliderview in cellForRowAtIndexPath slider.value = yourvalue;
The problem is that cellForRowAtIndexPath is called not just once, but every time that the tableView need to render that cell... So you have to be sure that only initialize theSlider the first time is called...
The best approach is to define a custom UITableViewCell and put there a property that would store theSlider, then, when cellForRowAtIndexPath is called, check if it is already initialized or not, see:
// If the slider is not yet initialized, then do it
if(cell.theSlider == nil)
{
// Init...
}
This is really from "cellForRowAtIndexPath" method . Every time when you are scrolling every cell is getting nil and reinitialise it. Better you can try with creating custom cell class(BY creating sub class of UITableViewCell) and also the defining slider in condition "if (cell == nil)".

UITableView Reuse Causing Broken Cells

When scrolling my UITableView (tends to be when I scroll it fast) the data for my cells gets mixed up, so labels might be repeated etc.
I understand that reusing the cells probably causes this, but what if the user scrolls down the list really quickly and all the cells get mixed up, how am I supposed to avoid this?
Thanks.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"VideoListCell";
VideoListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[VideoListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
if (isPlaylistView)
{
//Fill cell with data
}
else if (isPlaylistDetailView || isSearchResultsView)
{
//Fill cell with data
}
else
{
//Playlist button and uploads
if (indexPath.section == 0)
{
//Fill cell with data
}
else
{
//Fill cell with data
}
}
return cell;
}
You generally use this kind of code:
cell = dequeReusableCell;
if (cell == nil) {
create cell;
initialize cell;
}
fill cell with actual data from current row
return cell;
If you will move code "fill cell with actual data from current row" into "if" — you will get the kind of behavior you get right now.
So the answer will be "fill cell with data after you initialize it, outside of "if (cell == nil)" block.
UITableView will ever only dequeue a cell for reuse if the position that the cell was in is currently off-screen. So you don't have to worry about "mix-ups".
static NSString *cellIdentifier=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell==nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
}
I think it will be helpful to you.
set dequeueReusableCellWithIdentifier to nil for example..
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
UPDATE:
See this Example... i load many data in the cell with also my custom Gridview...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier = #"gridCell";
UITableViewCell *gridCell = [tableView dequeueReusableCellWithIdentifier:nil];
if(gridCell == nil)
{
gridCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
return gridCell;
}
hope this help you....
In your custom cell class override prepareForReuse method. In this method set text of your labels to nil and set imageview's image to nil also. This function is called everytime when a cell is reused so your problem will be solved by this. May be like this
- (void)prepareForReuse{
[super prepareForReuse];
self.titleLabel.text = nil;
self.unitImageView.image = nil;
}

protect cell.textLabel.text on scroll event of UITableView

How can I protect Text of UITableViewCell, which gets changed on scrolling of the UITableView.
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(indexPath.row != [destinationList count])
{
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.customLable.text = #"MyCustomLabel";
else
{
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Static Text to be set";
[cell.customLable removeFromSuperview];
}
Problem: Every time I scroll the UITableView, #"Static Text to be set" gets overwritten on #"MyCustomLabel".
How can I prevent this? I want all the cells of UITableView to retains their TextLabels through Table's LifeTime.
Two possible answers:
Generally it doesn't matter. Reusing the cell is how it's supposed to work and you should fully "reset" each cell each time. You shouldn't be storing state in the cell anyway
Create a new reuseIdentifier, one for the custom label and another for the static text
They will all retain their UILabels property, because cells get reused which is why you use:
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
However UITableView uses lazy loading meaning it ONLY keeps in memory visible UITableViewCells, therefore when you scroll the now invisible cells get reused, and now the new visible cells have the same UILabel as the ones that you can no longer see. That means there is really just a handful of UITableViewCells getting reused every time.
This is why in the docs UITableViewCell in the discussion for the instance method prepareforReuse:
If a UITableViewCell object is reusable—that is, it has a reuse identifier—this method is invoked just before the object is returned from the UITableView method dequeueReusableCellWithIdentifier:. For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. If the cell object does not have an associated reuse identifier, this method is not called. If you override this method, you must be sure to invoke the superclass implementation.
You should make different identifiers for different cells.
Anyway, to store something in UITableView is a wrong approach, it just to display data, not to store.
Try this
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = nil;
cell.customLabel.text = nil;
if(indexPath.row != [destinationList count])
{
cell.customLable.text = #"MyCustomLabel";
}
else
{
cell.textLabel.text = #"Static Text to be set";
}
why do you remove the custom label? Just remove the text of the label.
if(indexPath.row != [destinationList count])
{
/* ... */
cell.textLabel.text = #"";
cell.customLable.text = #"MyCustomLabel";
else
{
/* ... */
cell.textLabel.text = #"Static Text to be set";
cell.customLable.text = #"";
}
and make sure that does labels are transparent.

Accessing indexPath from custom UITableViewCell

I'm trying to create a UITableView to allow the user to enter data, similar to a lot of the settings UITableViews, with some textfields and callouts to other tableviews for checkboxes. For such a common feature in apps, this does not seem to be very straight forward.
I'm having trouble accessing the indexPath.row from my custom UITableViewCell. Here is where I allocate my custom UITableViewCell.
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[TextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
In my TextField class's #implementation, in - (id)initWithStyle: I'm trying to access the indexPath with:
NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell:self];
... in order to set the textfield's tag like:
textRow = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
textRow.tag = [indexPath row];
Could anyone please shed some light on my problem or point me in the direction of creating basic setting-style TableViews programatically.
Thank you
I think the problem might be that at the time of initialisation of your cell it hasn't been added to the UITableView - hence self.superview is returning nil.
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[TextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setTag:indexPath.row];
You will need to add a setTag: method to your TextFieldCellClass. I presume that code was inside cellForIndexPath or whatever, so indexPath will be passed to that method.
The set tag method should look something like this:
-(void)setTag:(int)tag {
textRow.tag = tag;
}

UITableView doesn't reuse cells?

Good morning all.
I'm having a small crisis with table views in a 3.1 app. I have a table view with some complex tableViewCells being loaded from a nib, and they're not being reused. Feeling it might have something to do with loading them from a nib, I decided to try a simple test project to see if cells are being reused using nothing but the basic apple template code. I started with the Navigation Based Template and here's the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
cell.textLabel.text = [NSString stringWithFormat:#"%d", indexPath.row];
return cell;
}
I have a breakpoint set at the following line, and it's getting called on every pass.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]
Setting the reuseIdentifier in the constructor as such:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"] autorelease];
}
Yields the same result, no cell reuse.
Thanks in advance for any help you can offer!
The table will usually create and use a few cells (5 or so usually) before it needs to start reusing them. This of course depends on how big they are and how many appear on screen at any given time. Nothing to fret about.
I am not sure what you mean by everytime, everytime the app opens ?
Run the code with object allocation tool and look at the graph for object allocations as you scroll through the tableview . If object allocations are increasing linearly even after few scrolls . Then you have a problem.
Try to make the CellIdentifier static, e.g.
static NSString *CellIdentifier = #"Cell";