43

で無限スクロールを行うにはどうすればよいUITableViewですか? UIScrollViewApple が WWDC のビデオの 1 つで実演したを使用してそれを行う方法を知っています。で次のことを試しましたtableView:cellForRowAtIndexPath:

if (indexPath.row == [self.newsFeedData_ count] - 1)
{
    [self.newsFeedData_ addObjectsFromArray:self.newsFeedData_];
    [self.tableView reloadData];
}

しかし、これは失敗します。他のアイデアはありますか?

4

9 に答える 9

56

UITableView の一番下に到達したタイミングを知る必要がある場合は、そのデリゲートになり (UIScrollView のサブクラスであるため)、 -scrollViewDidScroll: デリゲート メソッドを使用して、テーブルのコンテンツの高さと実際のスクロール位置を比較します。

編集(このようなもの):

- (void)scrollViewDidScroll:(UIScrollView *)scrollView_ 
{   
    CGFloat actualPosition = scrollView_.contentOffset.y;
    CGFloat contentHeight = scrollView_.contentSize.height - (someArbitraryNumber);
    if (actualPosition >= contentHeight) {
        [self.newsFeedData_ addObjectsFromArray:self.newsFeedData_];
        [self.tableView reloadData];
     }
}
于 2012-05-01T21:15:45.430 に答える
18

以下を使用して、上部をプルして更新する無限スクロール、および/またはスピナーホイールを使用して下部を連続的にスクロールすることをサポートできます。

https://github.com/samvermette/SVPullToRefresh

SVPullToRefreshUITableView底に達したときにロジックを処理します。スピナーが自動的に表示され、コールバック ブロックが起動されます。ビジネス ロジックをコールバック ブロックに追加します。

次に例を示します。

#import "UIScrollView+SVInfiniteScrolling.h"

// ...

[tableView addInfiniteScrollingWithActionHandler:^{
    // append data to data source, insert new cells at the end of table view
    // call [tableView.infiniteScrollingView stopAnimating] when done
}];

このプロジェクトは、CocoaPodsを使用してプロジェクトに追加するか、プロジェクトに直接コンパイルできます。

于 2013-03-09T01:02:27.977 に答える
17

これは、私がまとめた無限スクロール UITableView の非常に迅速で完全なデモです...

@interface InfiniteScrollViewController ()

@property (nonatomic) NSMutableArray *tableViewData;
@property (nonatomic) BOOL loadingMoreTableViewData;

@end

@implementation InfiniteScrollViewController

- (void)viewDidLoad {
    self.tableViewData = [[NSMutableArray alloc] init];
    [self addSomeMoreEntriesToTableView];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.tableViewData.count + 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    if (indexPath.row < self.tableViewData.count) {
        cell.textLabel.text = [self.tableViewData objectAtIndex:indexPath.row];
    } else {
        cell.textLabel.text = @"Loading more data...";

        // User has scrolled to the bottom of the list of available data so simulate loading some more if we aren't already
        if (!self.loadingMoreTableViewData) {
            self.loadingMoreTableViewData = YES;
            [self performSelector:@selector(addSomeMoreEntriesToTableView) withObject:nil afterDelay:5.0f];
        }
    }

    return cell;
}

- (void)addSomeMoreEntriesToTableView {
    int loopTill = self.tableViewData.count + 20;
    while (self.tableViewData.count < loopTill) {
        [self.tableViewData addObject:[NSString stringWithFormat:@"%i", self.tableViewData.count]];
    };
    self.loadingMoreTableViewData = NO;
    [self.tableView reloadData];
}

@end
于 2013-02-22T16:03:35.163 に答える
12

「UITableView」は、「scrollViewDidScroll」メソッドの「UIScrollView」と同じです。

そのため、無限スクロールを簡単にエミュレートできます。

  1. 円形テーブルをエミュレートするために頭と尾が一緒に結合されるように、配列を2倍にします

  2. 次のコードを使用して、ユーザーがテーブルの最初または最後に到達する傾向があるときに、2 倍のテーブルの最初の部分と 2 倍のテーブルの 2 番目の部分を切り替えます。

:

/* To emulate infinite scrolling...

The table data was doubled to join the head and tail: (suppose table had 1,2,3,4)
1 2 3 4|1 2 3 4 (actual data doubled)
---------------
1 2 3 4 5 6 7 8 (visualising joined table in eight parts)

When the user scrolls backwards to 1/8th of the joined table, user is actually at the 1/4th of actual data, so we scroll instantly (we take user) to the 5/8th of the joined table where the cells are exactly the same.

Similarly, when user scrolls to 6/8th of the table, we will scroll back to 2/8th where the cells are same. (I'm using 6/8th when 7/8th sound more logical because 6/8th is good for small tables.)

In simple words, when user reaches 1/4th of the first half of table, we scroll to 1/4th of the second half, when he reaches 2/4th of the second half of table, we scroll to the 2/4 of first half. This is done simply by subtracting OR adding half the length of the new/joined table.
*/


-(void)scrollViewDidScroll:(UIScrollView *)scrollView_ 
{  

    CGFloat currentOffsetX = scrollView_.contentOffset.x;
    CGFloat currentOffSetY = scrollView_.contentOffset.y;
    CGFloat contentHeight = scrollView_.contentSize.height;

    if (currentOffSetY < (contentHeight / 8.0)) {
    scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY + (contentHeight/2)));
    }
   if (currentOffSetY > ((contentHeight * 6)/ 8.0)) {
       scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY - (contentHeight/2)));
    }

}

PS - NT Time Table (Lite) というアプリの 1 つでこのコードを使用しました。プレビューが必要な場合は、アプリをチェックアウトできます: https://itunes.apple.com/au/app/nt-time-table-lite/id528213278?mt=8

テーブルが短すぎる場合がある場合は、上記のメソッドの最初に if ロジックを追加して、たとえばデータ数が 9 未満の場合にメソッドを終了できます。

于 2012-07-12T04:54:39.453 に答える
3

通常、私はオーバーライドscrollViewDidEndDeceleratingし、その中にコードを入れて、より多くのデータを要求します。
例:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

    float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;

    if (endScrolling >= scrollView.contentSize.height){
        //put here your code

    }
}

最近、無限スクロールを実装する UITableView のサブクラスを GitHub にアップロードしました。
ここからダウンロードできます:
https://github.com/alchimya/iOS-LazyTableView

于 2015-07-16T12:40:42.520 に答える
1

オーバーライドするのではなく、layoutSubviews でこれを最適に行うことができます。これが私がそれを実装した方法です。ここで実装の詳細を知ることができます

- (void)layoutSubviews{
[super layoutSubviews];

if(self.delegateForViews){

    CGPoint contentOffset = self.contentOffset;

    if([self.delegateForViews noOfViews]>numOfReusableViews){
        NSUInteger centerIndex=visibleViews.count/2;
        NSUInteger noOfViews=[self.delegateForViews noOfViews];
        UIView *centerView=[visibleViews objectAtIndex:centerIndex];

        CGPoint centerViewOrigin=centerView.frame.origin;
        CGSize centerViewSize=centerView.frame.size;
        CGFloat offsetDifference=contentOffset.x-centerViewOrigin.x;
        CGFloat offsetDifferenceAbs=fabs(contentOffset.x-centerViewOrigin.x);

        if(offsetDifferenceAbs>=centerViewSize.width){

            if(offsetDifference<0){
                currentPosition--;
            }else{
                currentPosition++;
            }

            self.contentOffset=centerViewOrigin;

            currentPosition=[self getPosition:currentPosition noOfViews:noOfViews];

            [self.delegateForViews clearView:centerView];
            [self.delegateForViews setupView:centerView forPosition:currentPosition];

            for (int i=centerIndex-1; i>=0; i--) {
                UIView* prevView=[visibleViews objectAtIndex:i];
                [self.delegateForViews clearView:prevView];
                [self.delegateForViews setupView:prevView forPosition:
                        [self getPosition:currentPosition-1 noOfViews:noOfViews]];
            }

            for (int i=centerIndex+1; i<visibleViews.count; i++) {
                UIView* nextView=[visibleViews objectAtIndex:i];
                [self.delegateForViews clearView:nextView];
                [self.delegateForViews setupView:nextView forPosition:
                        [self getPosition:currentPosition+1 noOfViews:noOfViews]];
            }

        }
    }

}

}
于 2012-11-19T16:56:44.460 に答える
0

シンプルで必要なものすべてを提供してくれたのは、次のクラスです。

https://github.com/jakemarsh/JMStatefulTableViewController

JMSStatefulTableViewController をサブクラス化するだけで、上書きする必要がある 3 つのメソッドがあります。

  • 初期データを取得するために init で呼び出されるもの
    • statefulTableViewControllerWillBeginInitialLoading
  • ユーザーが引っ張ってリフレッシュしたときに1つ
    • statefulTableViewControllerWillBeginLoadingFromPullToRefresh
  • 無限スクロール (次のページ) が呼び出されたときの 1 つ
    • statefulTableViewControllerWillBeginLoadingNextPage

これはCocoapodsからも使用できます。

于 2014-01-21T12:20:12.863 に答える