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をスクロールする方法には(多分)二つあります。
- ビュー内部をドラッグする。
- ステータスバーをタップし、一番上までスクロールする。
このどちらかであることを検出できれば良い訳です。
もちろんサブクラス化してUIResponderのメソッドをオーバーライドしてもできますが、もうちょっと簡単な方法があります。
1についてはscrollViewDidScroll:
内部でUIScrollViewのプロパティdragging
を調べることで検出します。
2については、スクロール直前に呼び出されるscrollViewShouldScrollToTop:
と直後に呼び出されるscrollViewDidScrollToTop:
でフラグを建てることで検出します。
こんな感じで実装します。
@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
しかし、ドキュメントはしっかり書いてほしいものですね……