Reputation: 5
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
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
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