user1218464 user1218464 - 5 months ago 36
iOS Question

UIScrollview within UITableViewCell and maintaining scrollview page

I have a UIScrollView within a UITableViewCell for being able to scroll through images within a cell. However, as a cell is reused the scroll position/content is reloaded and therefore the cell doesn't remember what scroll position (page) it was on when it comes into view again.

What's the best way to have a scroll view within a UITableView cell and have it maintain position as it comes back into view. The AirBnB app (https://itunes.apple.com/us/app/airbnb/id401626263?mt=8) seems to have accomplished this for example.

Answer

You need to keep track of your scroll views' content offset in a property. In the example below, I do this with a mutable dictionary. In cellForRowAtIndexPath:, I give the scroll view a tag and set the controller as the delegate. In the scroll view delegate method, scrollViewDidEndDecelerating:, the scroll view's content offset is set as the object for the key corresponding to the scroll view's tag. In cellForRowAtIndexPath:, I check for whether the indexPath.row (converted to an NSNumber) is one of the keys of the dictionary, and if so, restore the correct offset for that scroll view. The reason I add 1 to the tags is because the table view has its own scroll view which has a tag of 0, so I don't want to use 0 as a tag for one of the cell's scroll views.

So in cellForRowAtIndexPath, you need something like this:

cell.scrollView.tag = indexPath.row + 1;
cell.scrollView.delegate = self;

if ([self.paths.allKeys containsObject:@(indexPath.row + 1)]) {
    cell.scrollView.contentOffset = CGPointMake([self.paths[@(indexPath.row + 1)] floatValue],0);
}else{
    cell.scrollView.contentOffset = CGPointZero;
}
return cell;

And in the delegate method:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView.tag != 0)
        [self.paths setObject:@(scrollView.contentOffset.x) forKey:@(scrollView.tag)];
}

paths is a property (NSMutableDictionary) that I create in viewDidLoad.