横に長いUITableViewを考えています。

  1. Cellは無限に増える可能性がある
  2. UITableView(UIScrollView)のオリジナルの挙動(慣性スクロールや、バウンス)はそのまま残したい
  3. 縦横スクロールは1タップで同時に行いたい
  4. できるだけカスタムクラスは作りたくない

という要件があります。

  • オリジナルのViewを作ってそれをScrollViewに貼り付けるという方法では、1. の要件を満たすのが複雑になります。
  • ScrollViewの上にTableViewを貼り付けて、縦ScrollはTableViewに、横ScrollはScrollViewにそれぞれ担当させると、一度に一方向へしかScrollが効かず、3. が満たされません。
  • TableViewCellの中にScrollViewまたはCollectionViewを乗せても、3. が満たされませんでした。
  • ScrollView上にTableViewを乗せそれぞれのUser Interaction EnableをNOにし、さらにその上にPanGestureを設定したUIViewを乗せて、UIViewで感知した縦横のPanGestureをScrollView、TableViewそれぞれに伝達しContentOffsetを操作しましたが、2. が満たされませんでした。

UITableViewの横スクロール問題はよく話題になるかとは思いますが、最善の(最も簡単で、オリジナルUIを継承しつつ、デバイス不可も少ない)方法はどのようなものなのでしょうか。
もし成功されている方がいらっしゃいましたら、アドバイスをお願いいたします。


回答してくださった皆さんのおかげで解決することができました。
結論としては、UICollectionViewを使用し、UICollectionViewLayoutを自作することですべての要件を満たすことができました。
以下、UICollectionViewLayoutのobjcのコードを転載しておきます。

#import "BidirectionalCollectionLayout.h" // UICollectionViewLayoutを継承

@implementation BidirectionalCollectionLayout {
    NSInteger cellCount;
    CGSize cellSize;
}

- (void)prepareLayout
{
    [super prepareLayout];
    cellCount = [self.collectionView numberOfItemsInSection:0];
    cellSize = CGSizeMake(2000.0f, 66.0f);
}

- (CGSize)collectionViewContentSize {
    return CGSizeMake(cellSize.width, cellCount * cellSize.height);
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *indexPathsArray = [self indexPathsForItemsInRect:rect];
    NSMutableArray *array = [NSMutableArray array];
    for (NSIndexPath *indexPath in indexPathsArray) {
        [array addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
    }
    return array;
}

- (NSArray *)indexPathsForItemsInRect:(CGRect)rect
{
    NSMutableArray *array = [NSMutableArray array];

    NSInteger minRow = MAX(0, (NSInteger)floor(rect.origin.y / cellSize.height));
    NSInteger maxRow = MIN(cellCount, (NSInteger)ceil((rect.origin.y + rect.size.height) / cellSize.height));
    for (NSInteger i = minRow; i < maxRow; i++) {
        [array addObject:[NSIndexPath indexPathForItem:i inSection:0]];
    }
    return array;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    CGFloat offsetY = indexPath.item * cellSize.height;
    CGRect frame = CGRectMake(0, offsetY, cellSize.width, cellSize.height);
    attributes.frame = frame;
    return attributes;
}

@end