Расширение событий прокрутки UIScrollView и мониторинга

Я хочу реализовать некоторые пользовательские, многоразовые и эффективные поведения прокрутки в приложении для iPhone, поэтому я расширяю UIScrollView своим настраиваемым элементом управления и желаю отслеживать движения прокрутки.

Теперь я знаю, что я мог бы назначить свой пользовательский элемент управления как UIScrollViewDelegate и внутренне отвечать на вызовы scrollViewDidScroll, но это мне не кажется правильным (возможно, я ошибаюсь).

Это не кажется правильным, поскольку делегат нацелен на конкретную логику пользовательского интерфейса, а элементы управления должны быть выше уровня выше. Это также означает, что мне нужно будет перенаправить вызовы делегатов, если класс приложения также назначил себя как делегат, который кажется неэффективным.

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

Глядя на файл UITableView.h, UITableView, похоже, не настроен как UISCrollViewDelegate, поэтому мне интересно, как он управляет этим (я предполагаю, что при переработке ячеек он должен отслеживать свою позицию относительно видимых границ).

Я новичок в этой платформе, поэтому, возможно, мне не хватает чего-то очевидного. Любая помощь была оценена.

Ответы

Ответ 1

Нашел! (полностью случайно)

Я смирился с тем, чтобы назначить подкласс UIScrollView как делегата для супер, а затем реализовать метод scrollViewDidScroll: delegate, однако частично с помощью реализации я получил исключение в середине моего метода scrollViewDidScroll. Один быстрый взгляд на трассировку стека показал, что мой метод делегирования фактически вызывается из setContentOffset:

Оказывается, если вы переопределите setContentOffset:, вы получаете вызов каждый раз, когда перемещается прокрутка! и он поставляется с удобной структурой contentOffset, чтобы сообщить вам, где сейчас просматривается прокрутка:)

- (void)setContentOffset:(CGPoint)contentOffset
{
    [super setContentOffset:contentOffset];

    NSLog(@"ViewDidScroll: %f, %f", contentOffset.x, contentOffset.y);
}

Ответ 2

Я согласен с вашей первоначальной оценкой. Если вы меняете логику прокрутки (а не на прокрутку), тогда это подкласс, а не делегат.

UIScrollView предназначен для подкласса и включает в себя небольшое обсуждение об этом в ссылке. В частности, это предложения, переопределяющие -touchesShouldBegin:withEvent:inContent:, pagingEnabled и touchesShouldCancelInContentView:, которые, вероятно, там, где вы хотите выполнить описанную вами работу.

Ответ 3

Если вы сомневаетесь, вы обязательно должны пойти на методы делегата, однако иногда (мне нужно было это делать только сейчас за последние 5 лет в iOS-dev) подклассы - это путь.

Ответ на Jo-el правильный для Obj-C. Здесь он находится в Swift:

class FeedScrollView: UIScrollView {

    override var contentOffset: CGPoint {
        willSet(newContentOffset) {
            print("About to set Offset: \(newContentOffset)")
        }
    }
}

Ответ 4

(Возможно, я ошибаюсь)

Думаю, что да. Не понимая детали вашего приложения, методы делегата звучат точно так, как вы хотите. Имейте в виду, что контроллер (подкласс UIViewController) также может быть делегатом его представления.

Ответ 5

Я думаю, что ретранслятор делегата - это то, что вы хотите. Это позволит вам использовать опубликованный API, который обычно рекомендуется, а не переопределяет функции, о которых вы не должны знать. Я согласен с тем, что это кажется более беспорядочным, чем должно было быть, но если в UIScrollViewDelegate есть крючки, которые вам нужны для ваших настроек, тогда это звучит как ваш лучший выбор.

Вы также можете предоставить собственный пользовательский объект/протокол делегирования для того, что UIViewController использует ваше представление прокрутки, чтобы сделать некоторую определенную логику просмотра.

Ответ 6

Вы можете использовать следующий протокол для прослушивания положения прокрутки:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    NSLog(@"scroll");
}

См. эта ссылка (документы Apple по UIScrollViewDelegate).

См. эту ссылку (некоторый код для настройки делегата).