user3491822
user3491822

Reputation: 5

How to call a method in the parent view controller from a cell of a cell?

The structure of my app currently looks like this: Collection View Controller -> Generic Cell with table view inside of it -> individual cells.

I would like to call a method in the collection view controller from one of the individual cells. So far I have implemented a delegate in the individual cell but if I can't seem to set my delegate in the collection view controller because I don't have an instance of it.

Furthermore, I have several cells inside the table view that are required to access the methods in the collection view controller.

Upvotes: 0

Views: 707

Answers (2)

Piyush
Piyush

Reputation: 1544

For that you can do like that :

In Collection View Controller -> .h file

@interface CollectionViewController : UICollectionViewController<ColectionCellDelegate>

@end

In Collection View Controller -> .m file

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return [self.collectionData count];
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CollectionCell *cell = (CollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionCell" forIndexPath:indexPath];
    cell.cellData = [self.collectionData objectAtIndex:indexPath.row];
    cell.delegate = self;
    return cell;
}

-(void)tableCellDidSelect:(UITableViewCell *)cell{
    NSLog(@"Tap %@",cell.textLabel.text);
    DetailViewController *detailVC = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    detailVC.label.text = cell.textLabel.text;
    [self.navigationController pushViewController:detailVC animated:YES];
}

In CollectionCell.h

@class CollectionCell;
@protocol ColectionCellDelegate
-(void)tableCellDidSelect:(UITableViewCell *)cell;
@end

@interface CollectionCell : UICollectionViewCell<UITableViewDataSource,UITableViewDelegate>
@property(strong,nonatomic) NSMutableArray *cellData;
@property(weak,nonatomic) id<ColectionCellDelegate> delegate;
@end

In CollectionCell.m

@implementation CollectionCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.cellData = [[NSMutableArray alloc] init];
    }
    return self;
}
-(void) awakeFromNib{
    [super awakeFromNib];
    self.cellData = [[NSMutableArray alloc] init];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [self.cellData count];
}

// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    cell.textLabel.text = [self.cellData objectAtIndex:indexPath.row];

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    [[self delegate] tableCellDidSelect:cell];
}

Upvotes: 0

Anurag
Anurag

Reputation: 141869

The responder chain can help.

The view can query the responder chain for the first target that can accept a message. Suppose the message is -fooBar, then the view can query the target using the method -[UIResponder targetForAction:sender:]

// find the first responder in the hierarchy that will respond to -fooBar
id target = [self targetForAction:@selector(fooBar) sender:self];

// message that target
[target fooBar];

Note that this communication is controlled by this method:

(BOOL)canPerformAction:(SEL)action 
            withSender:(id)sender;

This default implementation of this method returns YES if the responder class implements the requested action and calls the next responder if it does not.

By default, the first object that responds to that message will become the target so you may want to override the canPerformAction:withSender: if needed for some views or view controllers.

Upvotes: 1

Related Questions