UITableViewCell 中 CollectionView 的 ContentOffset 复用问题

在 iOS 应用开发时,常常会用到在 UITableViewCell 中嵌套使用 UICollectionView 的时候,例如:

这个时候如果左右滑动 UICollectionView 中的内容,会造成它的 ContentOffset 的只发生改变。当包含这个 UICollectionView 的 UITableViewCell 被复用的时候,导致 UICollectionView 的 ContentOffset 也被复用了。这样就会出现错位现象。
解决这个问题的方法就是将每个 UICollectionView 的 ContentOffset 值进行存储。
采用如下的方法:

1
@property (nonatomic, strong) NSMutableDictionary * contentOffsetDic;
1
2
3
4
5
6
7
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath {

MyCell * collectionCell = (MyCell *)cell;
NSInteger row = indexPath.row;
CGFloat horizontalOffset = collectionCell.collectionView.contentOffset.x;
self.contentOffsetDic[[@(row) stringValue]] = @(horizontalOffset);
}
1
2
3
4
5
6
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
MyCell * collectionCell = (MyCell *)cell;
NSInteger row = indexPath.row;
CGFloat horizontalOffset = [self.contentOffsetDic[[@(row) stringValue]] floatValue];
[collectionCell.collectionView setContentOffset:CGPointMake(horizontalOffset, collectionCell.collectionView.contentOffset.y)];
}

其中 contentOffsetDic 用于对 UICollectionView 的 ContentOffset 进行存储,然后在 -(void)tableView:(UITableView )tableView didEndDisplayingCell:(UITableViewCell )cell forRowAtIndexPath:(NSIndexPath)indexPath 和 -(void)tableView:(UITableView )tableView willDisplayCell:(UITableViewCell )cell forRowAtIndexPath:(NSIndexPath )indexPath 这两个 UITableView 的代理方法中进行 contentOffset 的存储和恢复。

但是值得注意的是,数据的加载往往分为更新和加载更多两种形式,在数据更新的时候最好要 contentOffsetDic 中的数据重置,因为更新数据可能导致原来对应的数据就不存在了。