Tae
Tae

Reputation: 1695

Return a custom cell from cellForRowAtIndexPath:

I ran into a trouble and I'm looking for help.

I need to save a identifier in a cell, so I did a subclass of UITableViewCell and added to it the identifier property. In my view controller I create the cells as follow:

- (SidebarCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell* tableViewCell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    SidebarCell * cell = (SidebarCell *)tableViewCell;
    Category *category = [categoryDataController.categories objectAtIndex:indexPath.row];
    cell.textLabel.text = category.name;

    if (category.checked == 1) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

The problem is that when I select one of the cells, the method cellForRowAtIndexPath: returns an UTableViewCell object instead of a SidebarCell, so I don't have access to the identifier property:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
    SidebarCell *cell = (SidebarCell *)[tableView cellForRowAtIndexPath:indexPath]; // Trying to cast from UITableViewCell to SidebarCell

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        [CategoryDataController updateRow:cell.identifier status:1]; // Here the app crashes
    } else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
        [CategoryDataController updateRow:cell.identifier status:0];
    }    
}

is there a way for cellForRowAtIndexPath: to return an Sidebarcell object?

Thanks beforehand.

Edit

The SidebarCell.h

#import <UIKit/UIKit.h>

@interface SidebarCell : UITableViewCell

@property (nonatomic) NSInteger identifier;

@end

SidebarCell.m:

#import "SidebarCell.h"

@implementation SidebarCell

@synthesize identifier;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

The error:

2012-04-24 09:21:08.543 Dongo[2993:11603] -[UITableViewCell identifier]: unrecognized selector sent to instance 0x6d87d50
2012-04-24 09:21:08.571 Dongo[2993:11603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell identifier]: unrecognized selector sent to instance 0x6d87d50'
*** First throw call stack:
(0x14b1052 0x1a65d0a 0x14b2ced 0x1417f00 0x1417ce2 0x116bc 0x48e71d 0x48e952 0xd1686d 0x1485966 0x1485407 0x13e87c0 0x13e7db4 0x13e7ccb 0x239d879 0x239d93e 0x3fea9b 0x2e85 0x2715 0x1)
terminate called throwing an exception(lldb) 

Upvotes: 3

Views: 13703

Answers (3)

Bhupendrasingh Lohar
Bhupendrasingh Lohar

Reputation: 173

In my case i have used custom cell of a class tempTableViewcell

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *identifier = @"cellidentifier";

    tempTableViewcell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }

    cell.textLabel.text = @"abc";
    return cell;
}

Upvotes: 0

lnafziger
lnafziger

Reputation: 25740

UITableViewCell* tableViewCell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

The above line of code must be returning a UITableViewCell and not a SidebarCell.

SidebarCell * cell = (SidebarCell *)tableViewCell;

Then on your second line you cast the cell to a SidebarCell, but you are simply lying to the compiler and telling it that it should be a SidebarCell when it is in fact not. When you cast something it needs to start out as the correct type.

Instead of those two lines, you should be creating an actual SidebarCell. How you do this depends on how you have defined it.

Let me know if it is in a storyboard, xib, or created in code and I can provide an example if needed.

EDIT Since you are creating the cell in code, you simply need to replace the first two lines in cellForRowAtIndexPath with this:

SidebarCell * cell = [[SidebarCell alloc] init];

Everything else looks like it should work as-is.

Upvotes: 2

gregheo
gregheo

Reputation: 4270

You should leave the tableView:cellForRowAtIndexPath: method signature intact: it should return (UITableViewCell *) and not your custom cell class. Since your SidebarCell is a subclass of UITableViewCell, it should all "just work". No need to call super or any of that:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SidebarCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
    if (cell == nil) {
        cell = [[SidebarCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:@"CellIdentifier@"];
    }
    // ... set up the cell here ...
    return cell;
}

In other methods, the cast should work just as you have it:

SidebarCell *cell = (SidebarCell *)[tableView cellForRowAtIndexPath:indexPath];

Upvotes: 4

Related Questions