aryaxt
aryaxt

Reputation: 77626

iOS - Detect UITableViewCell being moved out of the visible view?

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?

Upvotes: 5

Views: 8533

Answers (3)

Tim
Tim

Reputation: 226

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.

Upvotes: 1

aryaxt
aryaxt

Reputation: 77626

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

Upvotes: 4

rob mayoff
rob mayoff

Reputation: 385860

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.

Upvotes: 8

Related Questions