web-dev-qa-db-ja.com

contentOffsetを設定すると、プログラムでscrollViewDidScrollがトリガーされます

ページにいくつかのUIScrollViewがあります。それらを個別にスクロールすることも、一緒にロックして1つのものとしてスクロールすることもできます。問題は、ロックされているときに発生します。

UIScrollViewDelegatescrollViewDidScroll:を使用して動きを追跡します。変更したcontentOffsetUIScrollViewを照会し、contentOffsetプロパティを一致するように設定して、他のスクロールビューへの変更を反映します。

素晴らしい....余分な呼び出しがたくさんあることに気づいたこと以外は。スクロールビューのcontentOffsetをプログラムで変更すると、デリゲートメソッドscrollViewDidScroll:が呼び出されます。代わりにsetContentOffset:animated:を使用しようとしましたが、デリゲートでトリガーを取得しています。

scrollViewDidScroll:をトリガーしないようにcontentOffsetsをプログラムで変更するにはどうすればよいですか?

実装ノート...各UIScrollViewは、デリゲートパターンを使用して、さまざまなUIView値の調整を処理する提示UIViewControllerサブクラスにコールバックするカスタムcontentOffsetの一部です。

59
DBD

デリゲートコールバックをトリガーせずにUIScrollViewのコンテンツオフセットを変更することは可能ですscrollViewDidScroll:UIScrollViewの境界を設定し、Originを目的のコンテンツオフセットに設定します。

CGRect scrollBounds = scrollView.bounds;
scrollBounds.Origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
106
Tark

試して

id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;

私のために働いた。

76
Abhijit

UIScrollViewの既存のプロパティの使用はどうですか?

if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
    //your code
}
38
Kukosk

@Tarkの答えを単純化すると、次のようにscrollViewDidScrollを1行で起動せずにスクロールビューを配置できます。

scrollView.bounds.Origin = CGPoint(x:0, y:100); // whatever values you'd like
6
SimplGy

別のアプローチは、ScrollViewDidScrollデリゲートにロジックを追加して、コンテンツオフセットの変更がプログラムによってまたはユーザーのタッチによってトリガーされたかどうかを判断することです。

  • 「isManualScroll」ブール変数をクラスに追加します。
  • 初期値をfalseに設定します。
  • ScrollViewWillBeginDraggingでtrueに設定します。
  • ScrollViewDidScrollで、それが正しいかどうかを確認し、正しい場合にのみ応答します。
  • ScrollViewDidEndDeceleratingでfalseに設定します。
  • ScrollViewWillEndDraggingに、速度が0の場合にfalseに設定するロジックを追加します(この場合scrollViewDidEndDeceleratingは呼び出されないため)。
5
Jake MacMullin

これは質問に対する直接的な答えではありませんが、そのようなメッセージを見せかけのように見えるものを得ている場合は、境界を変更しているためである可能性もあります。私はいくつかのAppleを使用して、スクロールビューへのサブビューを削除および追加する「tilePages」メソッドを使用します。私の場合、クラッシュを見つけるのは非常に不可能でした。

私がやったことは、メインキューでコールをキューイングすることでした:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if(scrollView == yourScrollView) {
        // dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
        // The reason can be found here: http://stackoverflow.com/questions/9418311
        dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
    }
}
4
David H