Reputation: 10206
I have code here that generates a list of cells that contain buttons.
I'm pretty sure there is a way to make it so that I am creating 1 button object instead of 20, but I'm not quite sure how to implement that?
I need some guidance as to where to make it so I only create 1 button object.
Additionally, I might be making 20 cell objects when I only need 1 as well?
I don't totally understand how to utilize memory well yet.
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = @"TimesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//[cell sizeToFit];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if([cell.contentView viewWithTag:3] != nil){
[[cell.contentView viewWithTag:3] removeFromSuperview];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:@selector(customActionPressed:)
forControlEvents:UIControlEventTouchDown];
[button setTitleEdgeInsets:UIEdgeInsetsMake(-10.0f, 0.0f, 0.0f, 0.0f)];
button.frame = CGRectMake(5, 5, 310, 50);
button.tag = 3;
int rows = [yourDefaultActivities count];
int rowsl = rows - 1;
float r = 1+(((255-1+75)/rowsl)*(indexPath.row));
if(r > 255){
r = 255;
}
float g = 255-(((255-1+75)/rowsl)*(indexPath.row));
if(g < 0){
g = 255-fabsf(g);
}else{
g = 255;
}
float b = 1;
UIColor *thisColor = [UIColor colorWithRed:r/255 green:g/255 blue:b/255 alpha:1];
button.backgroundColor = thisColor;
button.clipsToBounds = YES;
button.layer.cornerRadius = 15;
button.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14];
[button setTitle:[[yourDefaultActivities objectAtIndex:indexPath.row] objectAtIndex:0] forState:UIControlStateNormal];
[button.titleLabel setTextColor:[UIColor blackColor]];
[button.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:14]];
[cell addSubview:button];
return cell;
}
EDIT: I tried to remove the buttons every time I created a new one, but I must be doing it wrong..
Upvotes: 0
Views: 91
Reputation: 104082
One button object can't appear in 8 cells at once -- you do need as many cells and buttons as will fit on the screen at any time (it looks like 8 or 9). But 8 or 9 cell with buttons in them should not cause any memory problems -- buttons aren't that expensive. The problem with the code you posted though, is that it is adding buttons every time cellForRowAtIndexPath is called, which happens a lot when you scroll. Since cells are reused, you don't want to be adding a button to a cell that already has one. The easiest solution, in my opinion, is to make a custom cell in the storyboard, and add you buttons there. You can still set their color in code based on the indexPath so you get the look you want. Alternately, you can check whether the cell (actually the cell.contentView which is where you should be adding them, not directly to the cell) has a subview of class UIButton, and only add a button if it doesn't already have one.
After Edit:
In answer to your comment, you don't need to make the rounded button in the storyboard, you can just add a button (type custom) to your subclassed cell, and then modify its look in code. Here is an example of what I mean. In this test app, I created a custom cell class (RDCell) and changed the class of the cell in the storyboard to that. I added a custom button to the cell, positioned and sized it with constraints, and made an IBOutlet to it in RDCell.h. Here is what I have in the table view controller:
#import "TableController.h"
#import "RDCell.h"
@implementation TableController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(RDCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.button.backgroundColor = [UIColor colorWithHue:.15 + (indexPath.row/30.0) saturation:1 brightness:1 alpha:1];
cell.button.layer.cornerRadius = 15;
cell.button.titleLabel.textColor = [UIColor blackColor];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[cell.button addTarget:self action:@selector(customActionPressed:) forControlEvents:UIControlEventTouchUpInside];
cell.button.tag = indexPath.row;
return cell;
}
-(void)customActionPressed:(UIButton *) sender {
NSLog(@"button pressed in row: %d",sender.tag);
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:sender.tag inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
This was the resultant view:
I put a log in initWithCoder for RDCell, and it's called only 12 times (the max. number of cells on the screen at any one time), so there's never more than 12 cells or 12 buttons.
Upvotes: 2