Reputation: 139
I'm trying to find a way to not have code being duplicated when I set up custom cells in my table view. I currently have a BaseCell class, subclassed from UITableViewController and then two subclasses of BaseCell: CellTypeOne and CellTypeTwo. This is the sort of setup I'm using at the moment:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *type = [self.rowTypes objectAtIndex:indexPath.row];
if ([type isEqualToString:@"Type 1"]) {
CellTypeOne *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 1"];
cell.picture.image = // An image
cell.caption.text = // A caption
cell.author.text = // An author
return cell;
}
else if {[type isEqualToString:@"Type 2"]) {
CellTypeTwo *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 2"];
cell.picture.image = // An image
cell.caption.text = // A caption
cell.number.text = // A number
return cell;
}
}
As some of the properties being set are the same for either cell type, I'm wondering if there's a way to do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *type = [self.rowTypes objectAtIndex:indexPath.row];
id cell;
if ([type isEqualToString:@"Type 1"]) {
cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 1"];
// Cast cell to (CellTypeOne *)?
cell.author.text = // An author
}
else if {[type isEqualToString:@"Type 2"]) {
CellTypeTwo *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 2"];
// Cast cell to (CellTypeTwo *)?
cell.number.text = // A number
}
cell.picture.image = // An image
cell.caption.text = // A caption
return cell;
}
This way I can do class specific setup for each subclass and then do generic setup for both. The only way I've gotten this to work is by casting cell each time I need to use it, something like this:
[(BaseCell *)cell picture].image = // An image
Having to cast cell on each line seems like more work than having a couple of lines of duplicated code to begin with, but I'm just trying to figure out the best way to go about this.
Upvotes: 2
Views: 328
Reputation: 726489
You can make the cell
variable of type BaseCell*
to avoid casts outside ifs:
BaseCell *cell;
if ([type isEqualToString:@"Type 1"]) {
cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 1"];
[[cell author] setText:/*an author*/];
} else if {[type isEqualToString:@"Type 2"]) {
cell = [tableView dequeueReusableCellWithIdentifier:@"Cell 2"];
[[cell number] setText: /* a number */];
}
cell.picture.image = // An image
cell.caption.text = // A caption
Alternatively, you can keep the type of id
, and use method invocation syntax rather than member (dot) syntax outside the ifs:
id cell;
// ... the code from your post
[[cell picture] setImage: /* an image */];
[[cell caption] setText: /* a caption */];
Finally, you can avoid casts and square brackets altogether by declaring additional variables inside your ifs:
BaseCell *cell;
if ([type isEqualToString:@"Type 1"]) {
CallTypeOne *cellOne = [tableView dequeueReusableCellWithIdentifier:@"Cell 1"];
cellOne.author.text = // An author
cell = cellOne;
} else if {[type isEqualToString:@"Type 2"]) {
CellTypeTwo *cellTwo = [tableView dequeueReusableCellWithIdentifier:@"Cell 2"];
cellTwo.number.text = // A number
cell = cellTwo;
}
Upvotes: 2