Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does UITableViewCell communicate with its UITableView?

I am currently creating a custom grid view, which means that I am creating a class that has a lot in common with UITableView. One of the things that I want to get right is the communication of the cells and the grid view.

I was therefore wondering how a table view cell talks to its table view. For example, how does the cell notify the table view that its delete button was tapped and the cell needs to be removed from the table view?

There are several possible scenarios, but I am not sure which one is being used by Apple since the headers of UITableView or UITableViewCell reveal this (or am I overlooking something).

Ultimately, the goal is to let the cell and the grid view communicate in private, that is, without exposing any public methods or protocols (if this is possible).

like image 258
Bart Jacobs Avatar asked May 30 '12 10:05

Bart Jacobs


1 Answers

Now a delete button might be a poor example because iOS has a built in method which allows you to delete rows and notify your datasource called:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

However, for the sake of understanding if you wanted to add a button to your tableview cell and have it perform an action that isn't in the standard iOS library you would create a delegate in your cell and set your tableview's datasource file as the delegate.

Basically you would subclass UITableViewCell like so

MyCustomCell.h

@protocol MyCustomCellDelegate;
@interface MyCustomCell : UITableViewCell
@property (nonatomic, unsafe_unretained) id <MyCustomCellDelegate> delegate; //Holds a reference to our tableView class so we can call to it. 
@property (nonatomic, retain) NSIndexPath *indexPath; //Holds the indexPath of the cell so we know what cell had their delete button pressed
@end

/* Every class that has <MyCustomCellDelegate> in their .h must have these methods in them */
@protocol MyCustomCellDelegate <NSObject>
- (void)didTapDeleteButton:(MyCustomCell *)cell;
@end

MyCustomCell.m

@synthesize delegate = _delegate;
@synthesize indexPath = _indexPath;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
    {
    /* Create a button and make it call to a method in THIS class called deleteButtonTapped */
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(5, 5, 25, 25);
    [button addTarget:self action:@selector(deleteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

    }
    return self;
}

/**
 * This is the method that is called when the button is clicked.
 * All it does is call to the delegate. (Whatever class we assigned to the 'delegate' property)
 */
- (void)deleteButtonTapped:(id)sender
{
    [self.delegate didTapDeleteButton:self];
}

Your TableView's datasource would look something like this.

MyDataSource.h

/* We conform to the delegate. Which basically means "Hey you know those methods that we defined in that @protocol I've got them and you can safely call to them" */
@interface MyDataSource : UIViewController <MyCustomCellDelegate, UITableViewDelegate, UITableViewDataSource>
 @property (nonatomic,retain) NSArray *tableData;//We will pretend this is the table data
 @property (nonatomic,retain) UITableView *tableView;// We will pretend this is the tableview

@end

MyDataSource.m

//We will pretend we synthesized and initialized the properties
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier: @"MyCustomCell"];
    if (!cell) 
        cell = [[DownloadQueueCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: @"MyCustomCell"];
    cell.delegate = self;      // Make sure we set the cell delegate property to this file so that it calls to this file when the button is pressed.
    cell.indexPath = indexPath;// Set the indexPath for later use so we know what row had it's button pressed.
    return cell;
}


- (void)didTapDeleteButton:(MyCustomCell *)cell;
{

   // From here we would likely call to the apple API to Delete a row cleanly and animated
   // However, since this example is ignoring the fact that they exist
   // We will remove the object from the tableData array and reload the data
   [self.tableData removeObjectAtIndexPath:cell.indexPath];
   [self.tableView reloadData];

}

Basically, long story short. For your gridview you would just create a delegate method that tells the user a certain button was pressed.

like image 133
endy Avatar answered Nov 08 '22 07:11

endy