Weird behavior of indexPath.section in "cellForRowAtIndexPath:" - iphone

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;

Related

return type for CellForRowAtIndexPath

i have two tableviews in my view. i have issue in implementing the delegate methods. Can anyone help me on this. Here the problem is, this method requires a return value of type UITableViewCell right. what should i return?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView==ContactTableview)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *totalString = [ContactArray objectAtIndex:indexPath.row];
NSArray *afterSeparate = [[NSArray alloc]init];
afterSeparate = [totalString componentsSeparatedByString:#"+"];
NSString *cellText = [afterSeparate objectAtIndex:0];
//NSString *detailText = [afterSeprate objectAtIndex:1];
cell.textLabel.text = cellText;
//cell.detailTextLabel.text=detailText;
return cell;
}
if (tableView==ContactTableViewLabel)
{
static NSString *CellIdentifier = #"ContactListCustomCell";
ContactListCustomCell *cell = (ContactListCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ContactListCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (ContactListCustomCell *) currentObject;
break;
}
}
}
cell.ContactLabel.text = [LabelArray objectAtIndex:indexPath.row];
cell.ContactValue.text = [ValueArray objectAtIndex:indexPath.row];
return cell;
}
}
Use this edited code. It will also get rid you of any warning regarding return cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifier_contact = #"ContactListCustomCell";
UITableViewCell *cell;
if(tableView==ContactTableview)
{
if (cell == nil) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *totalString = [ContactArray objectAtIndex:indexPath.row];
NSArray *afterSeparate = [[NSArray alloc]init];
afterSeparate = [totalString componentsSeparatedByString:#"+"];
NSString *cellText = [afterSeparate objectAtIndex:0];
//NSString *detailText = [afterSeprate objectAtIndex:1];
cell.textLabel.text = cellText;
//cell.detailTextLabel.text=detailText;
}
if (tableView==ContactTableViewLabel)
{
ContactListCustomCell *cell1 = (ContactListCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell1 == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ContactListCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell1 = (ContactListCustomCell *) currentObject;
break;
}
}
}
cell1.ContactLabel.text = [LabelArray objectAtIndex:indexPath.row];
cell1.ContactValue.text = [ValueArray objectAtIndex:indexPath.row];
cell = (UITableViewCell*) cell1;
}
return cell;
}
There is no need to cast ContactListCustomCell as a UITableViewCell. You can use ContactListCustomCell as a subclass of UITableViewCell. You can update your code like this :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if(tableView==ContactTableview)
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
.
.
}
else if(tableView==ContactTableViewLabel)
{
static NSString *CellIdentifier = #"CustomCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"yourCellNibName" owner:self options:nil];
cell = self.yourCellProperty;
self.yourCellProperty = nil;
}
.
.
}
return cell;
}
GoodLuck !!!

Custom UITableViewCells repeats row after scrolling

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;
}
}
};

custom uitableviewcell

i building an chat app and i have a little problem, build cellforrowatindexpath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"UserCell";
UserCell *cell = (UserCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"UserCell"
owner:nil
options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (UserCell *) currentObject;
break;
}
}
}
NSString *nameValue = [self.names objectAtIndex:indexPath.row];
NSString *statusValue = [self.usersStatus objectAtIndex:indexPath.row];
cell.name.text = nameValue;
cell.status.text = statusValue;
return cell;
}
and in every cell i have a label what is hidden,and in:
-(void)chatHandlerNewMsg:(ChatHandler*)chat withInt:(NSString*)userId{
NSInteger tmp = [self.usersID indexOfObject:userId];
NSIndexPath *index = [NSIndexPath indexPathForRow:tmp inSection:0];
UserCell *cell = (UserCell*)[self.table cellForRowAtIndexPath:index];
[cell.newMsg setHidden:NO];
[self.table reloadData];
}
i check for new msg and if so i bring the uilabel from hidden to shown.
the problem is that the table view show this uilabel(that it is hidden by default) in other cells in the table view and not only in the specific one that we choose in :
UserCell *cell = (UserCell*)[self.table cellForRowAtIndexPath:index];
When ever you dequeue a cell you need to manually reset any state that a previous row may have set.
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell) {
//Reset cell state (make label hidden)
}
else
{
//Create new cell and configure (hide labels)
}
//Set any common attributes here (title)
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.