Aram Boyajyan
Aram Boyajyan

Reputation: 844

How to call parent table view method from a cell?

I have a custom cell with a label that should trigger a method of parent/table view controller.

Even though XCode provides me that method in autocomplete suggestions, it throws an error when I tap on that particular label:

UITableViewWrapperView showUserProfile unrecognized selector sent to instance

This is my code:

    @implementation ItemTableViewCell

    @synthesize item;

    - (void)awakeFromNib
    {
        self.authorLabel.userInteractionEnabled = YES;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showUserProfile)];
        [self.authorLabel addGestureRecognizer:tap];
    }

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

    - (void)showUserProfile
    {
        id parentView = [self superview];
        [parentView showUserProfile];
    }

    @end

Thanks!

Upvotes: 3

Views: 6896

Answers (3)

Duyen-Hoa
Duyen-Hoa

Reputation: 15784

You can add the controller (your ViewController that hosts UITableView for example) to your customized cell. Then, you use something like:

if ([self.controller respondsToSelector:@selector("afunctioname")]) {
    [self.controller performSelector:@selector("afunctionname")];
}

Your customizedCell: MyTableViewCell header

@property (nonatomic, assign) id controller; 

In the method cellforRow;

MyTableViewCell *aCell = ...
aCell.controller = self
..
return aCell;

You can add parameters to this selector if the 'afunctioname' takes parameters. If you have multi parameters, use NSDictionary as parameter.

Upvotes: 1

Mischa
Mischa

Reputation: 17241

There is a difference between a view and a view controller. A view controller's class is UIViewController (or a subclass) and it has a property view of class UIView which it controls and which is the "visible part" of the view controller.

In the method

- (void)showUserProfile
{
    id parentView = [self superview];
    [parentView showUserProfile];
}

you call showUserProfile on the table view cell's superview but not on the view controller. As you don't know the internal implementation of a UITableView you cannot even be sure that the cell's superview is the same as your table view controller's view. In fact, it is not. Because as you can see from the error log the table view itself has a subview of class UITableViewWrapperView which contains all the cells. But this view doesn't know anything about the method you declared in your table view controller. That is why the app crashes.

For calling a method in your table view controller you can either declare a delegate as suggested by tdelepine or you can add an action to your button in your table view controller's tableView:cellForRowAtIndexPath: method right after dequeuing the cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"yourID"];
    [cell.yourButton addTarget:self action:@selector(showUserProfile) forControlEvents:UIControlEventTouchUpInside];
    // customize other properties of your cell
    return cell;
}

This would be the easiest way to go in my opinion.

Upvotes: 1

tdelepine
tdelepine

Reputation: 2016

it is not the good way to passing some actions to the tableview. You must use a delegate between the custom class UITableViewCell and your controller.

In your custom UITableViewCell.h

@protocol myUITableViewCellDelegate

@interface myUITableViewCell : UITableViewCell

@property (nonatomic, assign) id<myUITableViewCellDelegate> delegate;

@end

@protocol myUITableViewCellDelegate <NSObject>
-(void) cellDidTap:(myUITableViewCell*) sender
@end

In your custom UITableViewCell.m

...
- (void)showUserProfile
    {
        [self.delegate cellDidTap:self];
    }
...

In your controller

-(UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexpath
{
......
        cell.delegate = self
......
}

-(void) cellDidTap:(myUITableViewCell*) sender
{
        [self showUserProfile];
}

Upvotes: 4

Related Questions