Подтвердить что ты не робот

Настройка contentOffset программно запускает scrollViewDidScroll

У меня есть несколько UIScrollView на странице. Вы можете прокручивать их самостоятельно или блокировать их вместе и прокручивать их как один. Проблема возникает, когда они заблокированы.

Я использую UIScrollViewDelegate и scrollViewDidScroll: для отслеживания движения. Я запрашиваю contentOffset из UIScrollView, который был изменен, а затем отразил изменения в других видах прокрутки, установив их свойство contentOffset в соответствие.

Великий.... кроме того, что я заметил много дополнительных звонков. Программное изменение contentOffset моих представлений прокрутки запускает метод делегата scrollViewDidScroll: для вызова. Я попытался использовать setContentOffset:animated: вместо этого, но я все еще получаю триггер на делетете.

Как я могу программным образом модифицировать свои программные объекты контента, чтобы не запускать scrollViewDidScroll:?

Замечания по реализации.... Каждый UIScrollView является частью пользовательского UIView, который использует шаблон делегирования для обратного вызова к представляющему подклассу UIViewController, который обрабатывает координаты различных значений contentOffset.

4b9b3361

Ответ 1

Можно изменить смещение содержимого UIScrollView без запуска обратного вызова делегата scrollViewDidScroll:, установив границы UIScrollView с исходным значением, установленным на желаемое смещение содержимого.

CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;

Ответ 2

Try

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

Работал для меня.

Ответ 3

Как использовать существующие свойства UIScrollView?

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

Ответ 4

Упрощая ответ @Tark, вы можете поместить прокрутку без стрельбы scrollViewDidScroll в одну строку следующим образом:

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

Ответ 5

Это не прямой ответ на вопрос, но если вы получаете то, что кажется ложным, такие сообщения, это может быть ТАКЖЕ, потому что вы меняете границы. Я использую код примера Apple с методом "tilePages", который удаляет и добавляет subview в scrollview. Это редко приводит к появлению дополнительных сообщений scrollViewDidScroll:, вызываемых немедленно, поэтому вы попадаете в рекурсию, которую вы точно не ожидали. В моем случае я получил отвратительное невозможное найти крах.

То, что я закончил, заключалось в очередности вызова в главной очереди:

- (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]; });
    }
}

Ответ 6

Другой подход заключается в добавлении некоторой логики в делегат scrollViewDidScroll, чтобы определить, было ли изменение смещения содержимого запрограммировано или нажато пользователем.

  • Добавить логическую переменную isManualScroll в ваш класс.
  • Задайте начальное значение false.
  • В scrollViewWillBeginDragging задано значение true.
  • В вашей проверке scrollViewDidScroll убедитесь, что это правда, и ответьте только в том случае, если она есть.
  • В scrollViewDidEndDecelerating установите значение false.
  • В scrollViewWillEndDragging добавьте логику, чтобы установить значение false, если скорость равна 0 (поскольку scrollViewDidEndDecelerating не будет вызываться в этом случае).