scrollViewDidScroll вызывается со странным contentOffsetY - PullRequest
3 голосов
/ 23 марта 2019

У меня есть UIViewController, который содержит NSFetchedResultsController. После вставки строк наверх я хочу, чтобы строки были видны так, как они были до вставок. Это означает, что мне нужно сделать некоторые вычисления, чтобы сохранить contentOffSetY сразу после обновления. Вычисления верны, но я заметил, что scrollViewDidScroll вызывается после того, как он прокручивается до моего указанного contentOffsetY, это приводит к поврежденному состоянию. Это логирование:

Will apply an corrected Y value of: 207.27359771728516
Scrolled to: 207.5
Corrected to: 207.27359771728516
Scrolled to: 79.5 <-- Why is this logline here?

Вы можете напрямую клонировать пример проекта: https://github.com/Jasperav/FetchResultControllerGlitch (фиксация https://github.com/Jasperav/FetchResultControllerGlitch/commit/d46054040139afeeb648e1e0b5b113bd98685b4a, только самая последняя версия проекта дает сбои, теперь странный вызов метода scrollViewDidScroll пропал. Если вы исправьте ошибку, которую я присуждаю за вознаграждение. Просто клонируйте новейшую версию, запустите ее и немного прокрутите. Вы увидите странное смещение контента (глюки) ). Запустите проект, и вы увидите странный вывод. Это controllerDidChangeContent метод:

public func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    let currentSize = tableView.contentSize.height

    UIView.performWithoutAnimation {
        tableView.endUpdates()

        let newSize = tableView.contentSize.height
        let correctedY = tableView.contentOffset.y + newSize - currentSize

        print("Will apply an corrected Y value of: \(correctedY)")
        tableView.setContentOffset(CGPoint(x: 0,
                                           y: correctedY),
                                   animated: false)
        print("Corrected to: \(correctedY)")
    }
}

Если я позвоню tableView.layoutIfNeeded сразу после tableView.endUpdates(), делегат уже будет вызван. Что вызывает вызов метода делегата? Есть ли способ, которым он не прокручивается?

1 Ответ

6 голосов
/ 31 мая 2019

Я скачал твой код и сделал несколько настроек, чтобы исправить проблему с глюками.Вот что я сделал.

  1. установил estimatedRowHeight свойство представления таблицы для некоторого числа
    init() {
        super.init(frame: .zero, style: .plain)
        estimatedRowHeight = 50.0
        register(MyTableViewCell.self, forCellReuseIdentifier: "cell")
    }
создал функцию для обработки действия перезагрузки UITableView без изменения текущего contentOffset
    func reloadDataWithoutScroll() {
        let lastScrollOffset = contentOffset
        beginUpdates()
        reloadData()
        layoutIfNeeded()
        endUpdates()
        layer.removeAllAnimations()
        setContentOffset(lastScrollOffset, animated: false)
    }
Обновлена ​​функция controllerDidChangeContent для использования функции reloadDataWithoutScroll
    UIView.performWithoutAnimation {
        tableView.performBatchUpdates({
            tableView.insertRows(at: inserts, with: .automatic)
        })   
        inserts.removeAll()
        tableView.reloadDataWithoutScroll()
    }

Когда я выполняю эти изменения, он не прокручивается при добавлении новой строки.Тем не менее, он прокручивает, чтобы показать новую добавленную строку, когда текущий contentOffset равен 0. И я не думаю, что это будет проблемой, если говорить логически.

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