Implement polymorphism inside the cellForRowAtIndexPath method for UITableViewCells

I have a genericTableViewController- GTBVC- class that goes into two other view controllers, each of which has its own data array, which is passed to this one GTBVC.

Currently my code is as follows:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    id object = [self.genericArray objectAtIndex:indexPath.row];
    NSString *textNameOfObject = [[self.genericArray objectAtIndex:indexPath.row] performSelector:@selector(name)];

#warning - todo: Create a polymorphistic method for each uitableviewcells.

    if([object isMemberOfClass:[OXPersonModel class]]){
        OXFriendTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellFriendIdentifier forIndexPath:indexPath];
        cell.friendNameLabel.text = textNameOfObject;


        [PKQuickMethods setCornerRadiusForView:cell.friendImageView withCornerRadius:CGRectGetWidth(cell.friendImageView.frame)/2];
        cell.friendImageView.image = [UIImage imageNamed:@"image"];
        [cell.friendImageView setContentMode:UIViewContentModeScaleToFill];
        return cell;
    }
    else if([object isMemberOfClass:[OXTagPlaceCountModel class]]){
        OXTagTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellTagIdentifier forIndexPath:indexPath];
        cell.tagNameLabel.text = textNameOfObject;
        cell.tagPlacesCountLabel.text = [[self.genericArray objectAtIndex:indexPath.row] performSelector:@selector(totalPlacesCountString)];
        return cell;
    }
    return nil;
}

So far this method is not so bad. However, since I want to make my code scalable for the future - when I expand the program to serve other cells and product types, I will need to ensure its easy implementation.

Polymorphism comes to mind. I thought that for each subclass of UITableView it is necessary to implement a common method name, for example -[cell updateForModelObject:], so that cellForRowAtIndexPaththere are only a few lines of code at the end .

, , . , , self.genericArray.

cellForRowAtIndexPath - if?

+4
3

, , . :

GTBVC , :

@protocol GTBVCCellConfiguration
   -(void)updateForModelObject:(id)anObject;
@end

UITableViewCell, . "id" , .

, Enum , :

typedef NS_ENUM(NSInteger, GenericTableViewMode) {
  case GenericTableViewModePerson,
  case GenericTableViewModePlace
};

GTBVC :

 @property (assign, nonatomic) GenericTableViewMode tableViewMode

GTBVC segue:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:#yourSegueIdentifierForPerson#]) {
       ((GenericTableViewController *)segue.destinationViewController).mode = GenericTableViewModePerson; 
   } else {
       // check for the next storyboard identifier and set the mode
   }
 }

cellForRowAtIndexPath ( ):

-(void)tableView:cellForRowAtIndexPath: {
   id object = [self.genericArray objectAtIndex:indexPath.row];

   UITableViewCell <GTBVCellConfiguration> *cell = nil;

   switch (self.mode) {
     case GenericTableViewModePerson:
         cell = [tableView dequeueResuableCellWithIdentifier:@"PERSON" forIndexPath:indexPath];
     case GenericTableViewModePlace:
         cell = [tableView dequeueResuableCellWithIdentifier:@"PLACE" forIndexPath:indexPath];
   }

   [cell updateForModelObject:object];
   return cell;
 }

, , tableview.

+3

protocol, , . , -(NSString*)cellIdentifier, . , . , , .

, , , .

+1

, ,

NSString *modelClassName = NSStringFromClass(model.class);
NSString *modelCellClassIdentifier = [modelClassName stringByAppendingString:@"TableViewCellIdentifier"];
UITableViewCell<ModelUpdatable> *cell = [tableView dequeuReusableCellWithIdentifier:modelCellClassIdentifier];
[cell updateWithModel:model];

, Person, PersonTableViewCellIdentifier. ( PersonTableViewCell.)

I use this technique so often that I have a macro to declare identifiers that I am going to reproduce from memory, so we consider it as a pseudo-code:

PRODeclareCellIdentifier(model) extern NSString *const model##TableViewCellIdentifier
PRODefineCellIdentifier(model) NSString *const model##TableViewCellIdentifier = @#model##TableViewCellIdentifier

In the heading of your cell you say PRODeclareCellIdentifier(Person). And in its implementation you will say PRODefineCellIdentifier(Person). I use macros sparingly, but they can be very, very useful for such a template.

0
source

Source: https://habr.com/ru/post/1568836/


All Articles