Reputation: 2746
I have a UITableViewCell with the following code where a user clicks on the "Save" button on a UITableViewCell. The image in the cell is saved, and the "Save" button is animated away, but the cell remains.
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.tableCell)
{
[tableView registerNib:[UINib nibWithNibName:@"LPContentTableViewCell" bundle:nil] forCellReuseIdentifier:@"ContentCell"];
self.tableCell = [tableView dequeueReusableCellWithIdentifier:@"ContentCell"];
}
[self.tableCell.saveImageButton addTarget:self action:@selector(saveImage:) forControlEvents:UIControlEventTouchUpInside];
return self.tableCell;
}
-(void)saveImage:(id)sender{
UIButton *button = (UIButton*)sender;
//image is saved
[UIView animateWithDuration:0.5f animations:^{
button.frame = newFrame;
}completion:^(BOOL finished) {
[button removeFromSuperview];
}];
Problem is, the cells not allocated at the time I press save also lose their save buttons. I casted the button as the sender. The button is removed and the buttons on the next few cells remain. However, cells further down in the UITableView appear when I scroll without the button. Ideas?
EDIT: suggestions incorporated
UIButton * cellButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[cellButton setTitle:@"Save" forState:UIControlStateNormal];
[cellButton addTarget:self action:@selector(saveImage:) forControlEvents:UIControlEventTouchUpInside];
cellButton.frame = CGRectMake(268, 95, 79, 23);
[self.tableCell.contentView addSubview:cellButton];
-(void)saveImage:(id)sender{
UIButton *button = (UIButton*)sender;
CGRect newFrame = button.frame;
newFrame.origin.x +=100;
[UIView animateWithDuration:0.5f animations:^{
button.frame = newFrame;
}completion:^(BOOL finished) {
[button removeFromSuperview];
}];
Upvotes: 0
Views: 1730
Reputation: 2911
You are breaking the MVC pattern with your implementation.
cellForIndexPath gets called whenever a cell is about to be presented on screen and should avoid needed to remember anything about your model (the images). Use indexPaths to get access to your model in methods.
The proper way to implement this is separate that out.
-(void) viewDidLoad
{
[super viewDidLoad];
// Register you nib here. You only need to do this once.
[self.tableView registerNib:[UINib nibWithNibName:@"LPContentTableViewCell" bundle:nil] forCellReuseIdentifier:@"ContentCell"];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Dequeuing will create or reuse cell. This is what that iOS silky smooth scrollin is all about
LPContentTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContentCell" forIndexPath: indexPath];
BOOL canSave = YES; //figure out if image at indexPath can be saved..
NSArray *targets = [cell.saveImageButton actionsForTarget:self forControlEvent:UIControlEventTouchUpInside];
if ([targets count] == 0) {
// Only add the target once per cell.. it would be easier to just add the target in IB instead of this method.
[cell.saveImageButton addTarget:self action:@selector(saveImage:) forControlEvents:UIControlEventTouchUpInside];
}
if (canSave) {
cell.saveImageButton.alpha = 1;
}
else {
cell.saveImageButton.alpha = 0;
}
}
-(void)saveImage:(id)sender {
UIButton *button = (UIButton*)sender;
LPContentTableViewCell *cell = [button superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Get image using indexPath and Save
CGRect newFrame = button.frame;
newFrame.origin.x +=100;
[UIView animateWithDuration:0.5f animations:^{
button.frame = newFrame;
}completion:^(BOOL finished) {
// Use alpha instead of removing the view so reused cells can just set the alpha back to 1
button.alpha = 0;
// Set the old frame back here too for reused cells.
button.frame = oldFrame;
}];
}
You LPContentTableViewCell's interface should look something like this.
@interface LPContentTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIButton *saveImageButton; // This needs to be connected with IB
@end
Upvotes: 3
Reputation: 883
You need to programmatically create a new button for every cell.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:@selector(aMethod:)
forControlEvents:UIControlEventTouchUpInside];`
And you can add a tag to it as some type of identifier.
[button setTag:rowNumber];
Upvotes: 0
Reputation: 2451
try this..
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.tableCell)
{
[tableView registerNib:[UINib nibWithNibName:@"LPContentTableViewCell" bundle:nil] forCellReuseIdentifier:@"ContentCell"];
self.tableCell = [tableView dequeueReusableCellWithIdentifier:@"ContentCell"];
}
UIButton * cellButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[cellButton setTitle:@"Save" forState:UIControlStateNormal];
[cellButton addTarget:self action:@selector(saveImage:) forControlEvents:UIControlEventTouchUpInside];
cellButton.frame = CGRectMake(127, 8, 50, 30);
[cell.contentView addSubview:cellButton];
return self.tableCell;
}
-(void)saveImage:(UIButton*)sender{
//image is saved
[UIView animateWithDuration:0.5f animations:^{
}completion:^(BOOL finished) {
[sender removeFromSuperview];
}];
Upvotes: 0