Custom UITableViewCells repeats row after scrolling - iphone

I'm looking for solution...
Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"ItemCardapio";
NSString *nibName = #"ItemCardapioCell";
ItemCardapioCell *cell = (ItemCardapioCell *) [self.restaurantsList dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
cell = (ItemCardapioCell *)[nib objectAtIndex:0];
[cell initCellWithRestaurant:#"" tipoRestaurante:#""];
}
return cell;
}

I find that with problems with cell repeating, the problem tends to occur when you put stuff you shouldn't in the if (cell == nil) bit.
The reason being is that the table view will end up using an incorrect re-used cell if you don't update certain aspects of your cell appropriately.
Try taking anything which directly changes your cell out of that if (cell == nil) bit, and it should stop problems with repeating cells.

Heres what I use for Custom cells:
static NSString *cellIdentifier = #"ItemCardapioCell";
ItemCardapioCell *cell = (ItemCardapioCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSLog(#"Creating Cell");
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ItemCardapioCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ItemCardapioCell class]])
{
cell = (ItemCardapioCell *)currentObject;
break;
}
}
};

Related

Weird behavior of indexPath.section in "cellForRowAtIndexPath:"

I have a weird problem with the indexPath.section from the cellForRowAtIndexPath: method.
I have a grouped tableview with 4 sections and I'm trying to apply a custom UITableViewCell for section 3, but it's not working.
When I try if(indexPath.section==0){...} it works (and for section==1 and section==2 as well) but it fails for section==3. (?)
I don't know why, that makes no sense.. Did someone already had this (strange) problem?
When I try if(indexPath.row==0){...} it works for all the 4 sections.. so..?!
Here is my code :
//ViewController.h
import "DirectionsTableViewCell.h"
DirectionsTableViewCell *directionsCell; // customized UITableViewCell
//ViewController.m
if (indexPath.section==3) {
static NSString *CellIdentifier = #"directionsCell";
DirectionsTableViewCell *cell = (DirectionsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DirectionsTableViewCell" owner:self options:nil];
cell = directionsCell;
}
return cell;
}
else {
static NSString *CellIdentifier = #"defaultCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Test";
return cell;
}
Problem solved !
I just added if(indexPath.row) and it works fine.
Finally you got this :
if(indexPath.section==3) {
if(indexPath.row) {
static NSString *CellIdentifier = #"directionsCell";
DirectionsTableViewCell *cell = (DirectionsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DirectionsTableViewCell" owner:self options:nil];
cell = directionsCell;
}
return cell;
}
}
Well, you're never allocating a DirectionsTableViewCell inside your if(cell == nil).
In this section of your code:
DirectionsTableViewCell *cell = (DirectionsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DirectionsTableViewCell" owner:self options:nil];
cell = directionsCell;
}
You never allocate a cell of type DirectionsTableViewCell for it to be reused later. I also notice you have an ivar named directionsCell of type DirectionsTableViewCell. Unless you're allocating and setting it up elsewhere, cell = directionsCell ends up assigning a nil object to your cell
Try this code instead and see if it works:
static NSString *CellIdentifier = #"directionsCell";
directionsCell = (DirectionsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(directionsCell == nil) {
directionsCell = [[DirectionsTableViewCell alloc] init]; //Or whatever your initializer is
}
return directionsCell;

Custom TableViewCells on a UIViewController?

I am trying to display a custom TableView on a UIViewController but am getting an error "UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:"
I had connected the TableView to datasource and delegate.
Any suggestion to go about implementing so or do I need a UITableViewController?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:nil options:nil];
for (id currentObjects in topLevelObjects){
if ([currentObjects isKindOfClass:[UITableView class]]){
cell = (CustomCell *) currentObjects;
break;
}
}
}
//---set the text to display for the cell---
cell.cellNameLabel.text = #"This is name";
cell.cellValueLabel.text = #"This is Value";
return cell;
ERROR:
//NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:nil options:nil];
//in above owner should be self
// if ([currentObjects isKindOfClass:[UITableView class]]){
change this line to
if ([currentObjects isKindOfClass:[CustomCell class]]){
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:self options:nil];//owner should be self
for (id currentObjects in topLevelObjects){
if ([currentObjects isKindOfClass:[CustomCell class]]){
cell = (CustomCell *) currentObjects;
break;
}
}
}
//---set the text to display for the cell---
cell.cellNameLabel.text = #"This is name";
cell.cellValueLabel.text = #"This is Value";
return cell;
}

request for member error when loading in customtableviewcell and setting its IBOUTLETS

I've spent the last 3 hours scratching my head at this issue because all seems correct, except I can't get through to my tableviewcell class to set the uilabels in my custom cell.
here is my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
//cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
//cell.imageViewSection =
// Set up the cell
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString *textTitle = [[stories objectAtIndex: storyIndex] objectForKey: #"title"];
NSURL *imageurl = [NSURL URLWithString:[[stories objectAtIndex: storyIndex] objectForKey: #"description"]];
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:imageurl]];
cell.imageViewSection = image;
cell.titleLabelText.text = textTitle;
return cell;
}
If someone can help me out it would be awesome :)
You should not rely on the cell always being returned as object at index 0 in the array. Do a simple loop to find the actual cell.
And add typecasts for the cell subclass you use
-(UITableViewCell*)tableView:(UITableView*)tableView
cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString* cellID = #"cellID";
MyCell* cell = (id)[tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCell"
owner:self
options:nil];
for (cell in nib) {
if ([cell isKindOfClass:[MyCell class]]) {
break;
}
}
}
// Safely do tuff to cell
return cell;
}
This snippet assumes that the cell is at least available, the behavior if no table view cell is returned is undefined.
You're assigning and casting TableViewCell to UITableViewCell variable and UITableViewCell does not have those outlets. Instead, you should do the following..
TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil];
cell = (TableViewCell *)[nib objectAtIndex:0];
}

Use multiple cell classes in tableViewController

Is there a way to use multiple uitableviewcell classes with nib files in the tableViewController?
There's this great tutorial video for how to create custom cell classes to be used in a tableViewController at the cellForRowAtIndexPath function that I'm pasting here in case anyone wants to see.
In this example though, they are only using one type of reusable cell class. This is from my own project but it's essentially what the tutorial presents. "videoCellEntry" is a custom cell that I have created with nib file videoEntryCell.xib, "videoEntry" is the class for each cell that I am configuring, and "videos" is an array of videoEntry.
I'm assuming to use multiple nib files, I can put some conditions to choose which nib file I want and then call a different loadNibNamed: portion like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"videoCellId";
videoEntryCell *cell =
(videoEntryCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if(<condition 1>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:self options:nil];
}
if(<condition 2>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:self options:nil];
}
cell = (videoEntryCell *)[nib objectAtIndex:0];
}
// Configure the cell.
videoEntry *vid = [videos objectAtIndex:indexPath.row];
[cell configureForVideoEntry:vid];
return cell;
}
But can the tableViewController handle multiple cell nib files? Or is there a better way? And wouldn't each cell require a different CellIdentifier depending on its nib file?
Yes, you can use multiple Nib-Files and multiple CellIdentifiers in the TableViewController. Just put your condition before the CellIdentifier. That's the way I've done it.
Some example inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method:
First define the variable cell:
UITableViewCell *cell;
Now the if-Block:
if(<condition 1>) {
static NSString *CellIdentifier = #"VideoCell1";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
if(<condition 2>) {
static NSString *CellIdentifier = #"VideoCell2";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
and finally:
return cell;
You can repeat the if-Block as often as you want. It's only important that you return a cell, which is not nil.

Why Can't I import a UITableViewCell subclass ? That's weird

It's like this, I created a UITableViewCell subclass called NewsItemCell, then I wanna use it in my FirstViewController.m, then I tried to import it, but the compiler keeps telling me this
Below is my code, it is driving me mad, thank you if you can help.
#import "NewsItemCell.h"
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize computers;
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NewsItemCellIdentifier";
NewsItemcell *cell = (NewsItemcell *)[tableView
dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NewsItemCell"
owner:self options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[NewsItemcell class]])
cell = (NewsItemcell *)oneObject;
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.computers objectAtIndex:row];
cell.newsTitle.text = [rowData objectForKey:#"Color"];
cell.newsDate.text = [rowData objectForKey:#"Name"];
return cell;
}
Jason
Should this code
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NewsItemCell"
owner:self options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[NewsItemcell class]])
cell = (NewsItemcell *)oneObject;
}
not be
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"NewsItemCell"
owner:self options:nil];
cell = newsItemCellView
}
and NewsItemcell *cell be NewsItemcell *newsItemCellView, as cell may confuse the compiler.