As soon as the cell is no longer visible on the screen I need to be notified.
UITableView already has a delegate method called tableView:didEndDisplayingCell:forRowAtIndexPath:
but this delegate method never gets called. And yes I do have the delegate for my UITableView set.
Any other ways to detect a cell being removed? I need to be able to save the content (inputs) of this cell before it's being reused by another item.
EDIT:
According to the documentation tableView:didEndDisplayingCell:forRowAtIndexPath:
is iOS 6 and higher API. Is there a way to achieve this on iOS 5?
On versions of iOS older than 6.0, the table view doesn't send the tableView:didEndDisplayingCell:forRowAtIndexPath:
message.
If you are using a subclass of UITableViewCell
, you can get the same effect on older versions of iOS by overriding didMoveToWindow
:
- (void)didMoveToWindow {
if (self.window == nil) {
// I have been removed from the table view.
}
}
You may need to give your cell a (weak or unsafe_unretained) reference back to your table view delegate so you can send the delegate a message.
However, you can't rely only on didMoveToWindow
for all versions of iOS. Before iOS 6, a table view always removed a table view cell as a subview before reusing it, so the cell would always receive didMoveToWindow
before being reused. However, starting in iOS 6, a table view can reuse a cell without removing it as a subview. The table view will simply change the cell's frame to move it to its new location. This means that starting in iOS 6, a cell does not always receive didMoveToWindow
before being reused.
So you should implement both didMoveToWindow
in your cell subclass, and tableView:didEndDisplayingCell:forRowAtIndexPath:
in your delegate, and make sure it works if both are called, or if just one is called.
I ended up using the combination of below to make sure that the logic applies to both iOS 5.0 and 6.0
CELL LOGIC
@protocol MyCellDelegate
- (void)myCellDidEndDisplaying:(MyCell *)cell;
@end
@implementation MyCell
// Does not work on iOS 6.0
- (void)removeFromSuperview
{
[super removeFromSuperview];
[self.delegate myCellDidEndDisplaying:(MyCell *)self];
}
@end
VIEWCONTROLLER LOGIC
@implementation MyViewcontroller
- (void)myCellDidEndDisplaying:(MyCell *)cell
{
IndexPath *indexPath = [self.tableView indexPatForCell:cell];
// do stuff
}
// Does not work on iOS below 6.0
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
}
@end
tableView:didEndDisplayingCell:forRowAtIndexPath:
is only available in iOS6 and later.
One (albeit slow) way to accomplish what you are after would be to use the scrollView delegate methods to monitor when the tableview scrolls. From there, call:
NSArray *visiblePaths = [tableView indexPathsForVisibleRows];
and check for any changes to the array of visible paths.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With