amitsbajaj
amitsbajaj

Reputation: 1304

Implementing a Custom Table View Cell (with labels and a custom size) using NSFetchedResultsController

I am working on a simple app which has the following premise:

I had this working very well with standard cells like subtitle, etc. I am using NSFetchedResultsController and I want to now deploy custom cells.

I changed the style to be a custom cell in the Storyboard and added three labels which would represent the name, title and amount (added by the user).

I created a custom class for the UITableViewCell and ensured that this table view cell was that custom reference class. I added the properties for the labels: nameLabel, amountLabel, titleLabel.

I imported this class into the full TableViewController class. Following tutorials online, it states to essentially just use the cellForRowAtIndexPath method with something like this:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  static NSString *cellIdentifier = @"TableCellID";

  TableCell *tablecell = (TableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];


  NSDictionary * dict = [self.tweetsArray objectAtIndex:indexPath.row];

  tablecell.title.text = [dict objectForKey:@"tweet"];

  UIImage *imageIcon = [UIImage imageNamed:[dict objectForKey:@"image"]];
  [tablecell.cellImage setImage:imageIcon];

  return tablecell;

}

That is not my code but referenced from: http://www.codigator.com/tutorials/ios-uitableview-tutorial-custom-cell-and-delegates/ but the concept is the same.

Because I am using NSFetchedResultsController, I actually have two methods for the cell:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    Transaction *transaction = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.nameLabel.text =[NSString stringWithFormat:@"%@", transaction.name];
    cell.amountLabel.text = [NSString stringWithFormat:@"%@", transaction.amount];
    cell.eventLabel.text = [NSString stringWithFormat:@"%@", transaction.title];
}

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

    static NSString *CellIdentifier = @"People";

    TransactionCell *cell = (TransactionCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Set up the cell...
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

This code does not work because the nameLabel, amountLabel is not actually recognised.

I have (like the code at the top) put all of the information into the cellForRowAtIndexPath, but then I get an error from the

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 

method because it has the following entry:

case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

I have tried changing the method signature of the

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

to be:

- (void)configureCell:(TransactionCell *)cell atIndexPath:(NSIndexPath *)indexPath {

but that just does not seem right to me and there are warnings.

So basically I'm not trying to achieve anything complicated. I am simply trying to create a custom cell with three labels - why is the "cell" from the cellForRowAtIndexPath not being recognised in the configureCell method?

Finally, the custom cell has a specific size, bigger than normal and that does not appear when the app is run; it remains normal. I did this in the inspector of the cell but also added the following code to the end of the table view class:

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
    tableView.rowHeight = 80;
}

But it remained the normal height.

Any assistance on this would be massively appreciated!

Thanks,

Upvotes: 0

Views: 1544

Answers (2)

Nicolas Manzini
Nicolas Manzini

Reputation: 8546

This is because you probably forgot to call

self.tableView registerClass:forCellReuseIdentifier:

Or

self.tableView registerNib:forCellReuseIdentifier:

in your viewDidLoad (assuming self.tableView point to your UITableView)

by the way do not implement both! If you made a xib for your cell, use registerNib alone. If you created a UITableViewCell subclass, use registerClass alone.

Upvotes: 1

Martin R
Martin R

Reputation: 539715

You have two options:

  • Change the signature of configureCell to

    - (void)configureCell:(TransactionCell *)cell atIndexPath:(NSIndexPath *)indexPath
    

    and add an additional cast in

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(TransactionCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;
    
  • Or leave the signature of configureCell as it is and cast inside the method:

    - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
        TransactionCell *tcell = (TransactionCell *)cell;
        Transaction *transaction = [self.fetchedResultsController objectAtIndexPath:indexPath];
        tcell.nameLabel.text = transaction.name;
        tcell.amountLabel.text = transaction.amount;
        tcell.eventLabel.text = transaction.title;
    }
    

    (Note that all the stringWithFormat: calls are unnecessary.)

I would use the second method, but that is just a matter of taste.

Upvotes: 1

Related Questions