scrollViewDidScroll:が「呼ばれる」問題

  • 24
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

UITableViewのメソッドscrollToRowAtIndexPath:atScrollPosition:animated:は、最新のiOS 6.1 doc setによると、

Invoking this method does not cause the delegate to receive a scrollViewDidScroll: message, as is normal for programmatically-invoked user interface operations.

(拙訳) このメソッドを呼び出しても、通常のプログラマチックに呼び出されたユーザインタフェース操作のように、デリゲートはscrollViewDidScroll:メッセージを受け取りません。

と書いてありますが、実際には呼び出されてしまいます。
では、ユーザがTableViewをスクロールした時にだけ処理をしたい(したくない)! という時にはどうしたらいいのか。


ユーザがTableViewをスクロールする方法には(多分)二つあります。

  1. ビュー内部をドラッグする。
  2. ステータスバーをタップし、一番上までスクロールする。

このどちらかであることを検出できれば良い訳です。
もちろんサブクラス化してUIResponderのメソッドをオーバーライドしてもできますが、もうちょっと簡単な方法があります。

1についてはscrollViewDidScroll:内部でUIScrollViewのプロパティdraggingを調べることで検出します。
2については、スクロール直前に呼び出されるscrollViewShouldScrollToTop:と直後に呼び出されるscrollViewDidScrollToTop:でフラグを建てることで検出します。


こんな感じで実装します。

MyTableViewDelegate

@interface MyTableViewDelegate : NSObject <UITableViewDelegate>
@property (nonatomic) BOOL scrollingToTop;
@end


@implementation MyTableViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.dragging || self.scrollingToTop) {
        ...
    }
}

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
    self.scrollingToTop = YES;
    return YES;
}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView {
    self.scrollingToTop = NO;
}

@end

しかし、ドキュメントはしっかり書いてほしいものですね……