Альтернатива для reloadData() UITableView?

У меня есть UISlider в повторно используемой ячейке табличного представления.
Как только значение изменяется, вызывается пользовательский метод valueChanged(), который запускает метод табличного представления reloadData(). reloadData() вызывает cellForRowAtIndexPath, и как только ячейка, в которой был изменен ползунок, загружается, он анимирует два ограничения, которые должны выглядеть так, как будто кнопка скользит справа от ячейки.

По сути, эффект, который я пытаюсь создать, заключается в том, что как только пользователь начинает двигать UISlider, начинается анимация и появляется кнопка.
Но вот в чем загвоздка: свойство isContinious UISlider установлено на true, чтобы убедиться, что анимация происходит. сразу и не задерживается до тех пор, пока пользователь не уберет палец с ползунка. Однако установка isContinious на true приводит к тому, что reloadData() (который был внутри моего пользовательского valueChanged()) вызывается МНОГО РАЗ с каждым маленьким слайдом, который фиксирует пользователь.

После некоторых исследований и опробования многих Тактика отладки, теперь я знаю, что как только вызывается reloadData(), любые запущенные анимации (которые все еще анимируются во время вызова reloadData()) прерываются и просто переходят в состояние, в котором они должны быть после завершения анимации.

Итак, резюмируя сценарий:

1) ползунок перемещается,
2) valueChanged() запускает reloadData(),
3) анимация начинает обновлять макет,
4) reloadData() немедленно вызывается снова, разрушая анимацию, начатую на шаге 3.

Все происходит так быстро, когда isContinious установлено в true, поэтому анимация не успевает завершиться до того, как reloadData() будет вызвана снова. Это разрушает анимацию и создает впечатление, что кнопка просто появляется на экране без анимации, хотя я знаю, что UIView.animate(withDuration:) вызывается и нормально выполняет свою работу. Мне было интересно, есть ли способ обновить таблицу без вызова reloadData(), так что в основном это альтернатива этому методу (я уже пробовал reloadCellAtIndexPath, и это дает точно такой же эффект). Если нет, есть ли способ абсолютно убедиться, что анимация завершается без прерывания каким-либо другим методом обновления макета?


person Freddy Benson    schedule 27.10.2016    source источник


Ответы (1)


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

    var timer = Timer()

    func valueChanged() {
        timer.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in
            //Call reload here
        }
        //Animate here
    }
person Josh Homann    schedule 27.10.2016
comment
Спасибо! Я не стал использовать таймер, но ваша идея запустить таймер из блока анимации привела меня к идее просто использовать настраиваемое логическое значение, которое проверяет, выполняется ли анимация. Я не знал, что блок завершения UIView animateWithDuration вызывается ПОСЛЕ завершения анимации. Раньше я всегда думал, что он вызывается сразу после запуска анимации и что логический параметр внутри блока завершения указывает, выполняется ли анимация. - person Freddy Benson; 27.10.2016
comment
После того, как я понял это, я просто создал собственное логическое значение isAnimating, которое было установлено в значение true при запуске анимации и значение false в блоке завершения, ПОСЛЕ завершения анимации. В моем методе valueChanged (который вызывается миллион раз в секунду) я просто проверяю, установлено ли для isAnimating значение false, и запускаю код reloadData() только в том случае, если это так. Работает как шарм. В общем, из-за того, что я неправильно понял цель блока завершения animateWithDuration, я сделал эту проблему намного сложнее, чем она оказалась. - person Freddy Benson; 27.10.2016