vinylDeveloper
vinylDeveloper

Reputation: 707

UITableViewCell subclass causing unrecognized selector sent issue

I'm subclassing UITableViewCell, and it's causing my app to crash... The issue I was having is my cells kept drawing over themselves, so the answer I found after searching is a subclass, but I'm having some issues. Here is my code.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    static NSString *requestCell = @"requestCell";

    RequestCell *cell;

    switch (indexPath.section) {
        {case 0:
            cell = [tableView dequeueReusableCellWithIdentifier:requestCell forIndexPath:indexPath];
            if (cell == nil) {
                cell = [[RequestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:requestCell];
            }

            //APP CRASHES ON THIS LINE 
            cell.requestTitle.frame = CGRectMake(60, 5, self.view.frame.size.width - 70, 30);
            cell.detailTitle.frame = CGRectMake(60, 30, self.view.frame.size.width - 70, 25);

            Request *request = [[Request alloc] init];
            request = self.isNotFilledList[indexPath.row];
            cell.requestTitle.text = request.productName;
            cell.detailTitle.text = request.dateRequested;
            cell.detailTitle.font = [UIFont systemFontOfSize:11.0];

            NSString *imageURL = @"myurl";
            imageURL = [imageURL stringByAppendingString:request.productImageName];

            cell.requestImageButton.frame = CGRectMake(5, 5, 50, 50);
            [cell.requestImageButton sd_setBackgroundImageWithURL:[NSURL URLWithString:imageURL] forState:UIControlStateNormal];

            NSLog(@"request name %@", request.productName);
            return cell;
        break;}

        {case 1:
            cell = [tableView dequeueReusableCellWithIdentifier:requestCell forIndexPath:indexPath];
            if (cell == nil) {
                cell = [[RequestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:requestCell];
            }

            Request *request = [[Request alloc] init];
            request = [self.isFilledList objectAtIndex:indexPath.row];
            cell.textLabel.text = request.productName;
            return cell;
            break;}

        default:
            break;
    }

    return cell;
}

And my RequestCell class

@interface RequestCell : UITableViewCell

@property (strong, nonatomic) UILabel *requestTitle;
@property (strong, nonatomic) UILabel *detailTitle;
@property (strong, nonatomic) UIButton *requestImageButton;

and .m file

#import "RequestCell.h"

@implementation RequestCell

- (void)awakeFromNib {
    // Initialization code
}

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


    }
    return self;
}

-(UILabel *)requestTitle
{
    if(!_requestTitle)
    {
        _requestTitle = [[UILabel alloc] init];
    }
    return _requestTitle;
}

-(UILabel *)detailTitle
{
    if(!_detailTitle)
    {
        _detailTitle = [[UILabel alloc] init];
    }
    return _detailTitle;
}


-(UIButton *)requestImageButton
{
    if(!_requestImageButton)
    {
        _requestImageButton = [[UIButton alloc] init];
    }
    return _requestImageButton;
}



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

    // Configure the view for the selected state
}

What am I doing wrong???

Original Code **Re-draws cells over top

switch (indexPath.section) {
        {case 0:
            cell = [tableView dequeueReusableCellWithIdentifier:requestCell forIndexPath:indexPath];
            if (cell == nil) {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:requestCell];
            }

            UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(55, 5, self.view.frame.size.width - 60, 30)];
            UILabel *detailTitle = [[UILabel alloc] initWithFrame:CGRectMake(55, 30, self.view.frame.size.width - 60, 25)];

            Request *request = [[Request alloc] init];
            request = self.isNotFilledList[indexPath.row];
            title.text = request.productName;
            detailTitle.text = request.dateRequested;

            NSString *imageURL = @"myurl";
            imageURL = [imageURL stringByAppendingString:request.productImageName];

            UIButton *keyImageButton = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 50, 50)];
            //[[keyImageButton imageView] setContentMode: UIViewContentModeScaleAspectFill];
            [keyImageButton sd_setBackgroundImageWithURL:[NSURL URLWithString:imageURL] forState:UIControlStateNormal];

            [cell addSubview:detailTitle];
            [cell addSubview:title];
            [cell addSubview:keyImageButton];

            NSLog(@"request name %@", request.productName);
            return cell;
        break;}

Upvotes: 1

Views: 194

Answers (2)

rdelmar
rdelmar

Reputation: 104082

If your cell is made in a storyboard, then initWithCoder: is the init method called, not initWithStyle:reuseIdentifier:. So, override that, and create your labels, and add them to the contentView there. Also, there no reason for an if cell == nil clause in your cellForRowAtIndexPath method, since your dequeue method is guaranteed to return a cell.

Another thing you should change is this,

Request *request = [[Request alloc] init];
request = self.isNotFilledList[indexPath.row];

You instantiate a Request object in that first line, but then throw that away by redefining it as self.isNotFilledList[indexPath.row] in the next line. You should just have,

Request *request = self.isNotFilledList[indexPath.row];

Upvotes: 3

Mike S
Mike S

Reputation: 11409

You don't need to manually instantiate the Cell instance variables. Try removing the extra functions

-(UILabel *)requestTitle
{
    if(!_requestTitle)
    {
        _requestTitle = [[UILabel alloc] init];
    }
    return _requestTitle;
}

-(UILabel *)detailTitle
{
    if(!_detailTitle)
    {
        _detailTitle = [[UILabel alloc] init];
    }
    return _detailTitle;
}


-(UIButton *)requestImageButton
{
    if(!_requestImageButton)
    {
        _requestImageButton = [[UIButton alloc] init];
    }
    return _requestImageButton;
}

in favor of this

@implementation RequestCell
@synethesize requestTitle;
@synthesize detailTitle;
@synthesize requestImageButton;

EDIT:

Ah I think I see the problem now. You are using dequeueReusableCellWithIdentifier:forIndexPath: which is new iOS 6 and designed to never return a nil cell (to prevent app crashes and developer convenience). So your if statement that follows is for the OLD dequeue method which is just dequeueReusableCellWithIdentifier

the fix should be changing this:

cell = [tableView dequeueReusableCellWithIdentifier:requestCell forIndexPath:indexPath];

to this:

cell = [tableView dequeueReusableCellWithIdentifier:requestCell];

more details can be found here

Upvotes: 0

Related Questions