Posts Tagged ‘Custom Cell’
UITableViews are awesome. They allow you to display a variety of information, can be customized extensively, take care of memory management and much much more. Since they only remember what’s currently on screen, getting a basic ToDo list up and running can be quite the challenging task for a rookie coder. In this post I’d like to show you how this can be achieved in just a few steps.
First, let’s get all the ingredients ready…
Basically, we need 3 things:
- UITableView to display stuff
- Data source array, that contains the stuff we want to display
- Dictionary, to keep track of what is checked / unchecked
On top of that, we also need:
- UITableViewCell to put inside our UITableView
- UILabel inside our UITableViewCell to display some text
- UIButton inside our UITableViewCell to check / uncheck this cell
@interface TableViewCellDemoViewController : UIViewController {
IBOutlet UITableView *tableView;
NSArray *dataSourceArray;
NSMutableDictionary *checkedDictionary;
}
- (void)checkButtonTapped:(id)sender forCellWithLabel:(NSString *)text;
@property (nonatomic, retain) IBOutlet UITableView *tableView;
@property (nonatomic, retain) NSArray *dataSourceArray;
@property (nonatomic, retain) NSMutableDictionary *checkedDictionary;
@end
Inside the .m file I need to properly create the cells…
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BaseCell *cell = (BaseCell *)[_tableView dequeueReusableCellWithIdentifier:@"BaseCell"];
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:@"BaseCell" owner:self options:nil] lastObject];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.cellLabel.backgroundColor = [UIColor clearColor];
cell.cellLabel.font = [UIFont fontWithName:@"Helvetica" size:17];
cell.cellLabel.text = [dataSourceArray objectAtIndex:indexPath.row];
cell.parentViewController = self;
//let's use the cellLabel.text as key inside our checkedDictionary. IMPORTANT: This only works, if information inside cellLabel.text is unique for every row. If you have the same text twice in your datasourceArray, this will cause to some unexpected behavior.
NSString *key = cell.cellLabel.text;
BOOL checked = [[checkedDictionary objectForKey:key]boolValue];
[cell.checkButton setBackgroundImage:(checked) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
return (UITableViewCell *)cell;
}
…and add a method, that will get called, if I tap on the check / uncheck button
- (void)checkButtonTapped:(id)sender forCellWithLabel:(NSString *)text {
UIButton *button = (UIButton *)sender;
//like above, we're using the information inside the label (text) as unique identifier = key
NSString *key = text;
BOOL checked = [[checkedDictionary objectForKey:key]boolValue];
//depending on whether the row has been checked before or not, we write YES / NO to our checkedDictionary
if (checked) {
[checkedDictionary setValue:@"NO" forKey:text];
checked = NO;
}
else {
[checkedDictionary setValue:@"YES" forKey:text];
checked = YES;
}
//finally set the new button background image
[button setBackgroundImage:(checked) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
}
Finally, I create an empty user interface for Interface Builder and add a UITableViewCell object to it. I also create a new class, named “BaseCell” and set it as custom class for my UITableViewCell.
After adding a UILabel and UIButton object to my cell, I properly link everything and my BaseCell.h file will look like this:
#import <UIKit/UIKit.h>
@interface BaseCell : UITableViewCell {
IBOutlet UILabel *cellLabel;
IBOutlet UIButton *checkButton;
UIViewController *parentViewController;
}
- (IBAction)checkButtonAction:(id)sender;
@property (assign) IBOutlet UILabel *cellLabel;
@property (assign) IBOutlet UIButton *checkButton;
@property (assign) UIViewController *parentViewController;
@end
Last but not least, the .m file will make a call to “checkButtonTapped” method inside my UITableViewController’s class like this:
- (IBAction)checkButtonAction:(id)sender {
if (self.parentViewController) { //call method inside TableViewCellDemoViewController and submit the sender object (= button) and the text inside the label. We will use the text as unique identifier (=key) inside our checkedDictionary (also part of TableViewCellDemoViewController class)
[self.parentViewController performSelector:@selector(checkButtonTapped: forCellWithLabel:) withObject:sender withObject:[self.cellLabel text]];
}
}
If we break down the steps, our app will basically perform the following tasks:
-
Set up custom UITableView cells, containing a UILabel and UIButton
-
If user taps on the button, make a call from BaseCell class to TableViewCellDemoViewController class and submit both the sender button and text inside the UILabel
-
Use the UILabel text to look up a matching key inside our “checkedDictionary” object
-
Change background image of the UIButton, depending on whether (3) exists and whether it is YES or NO.
