scrolltoitematindexpath всегда возвращается в ту же позицию

#swift #uiscrollview #uicollectionview

#swift #uiscrollview #uicollectionview

Вопрос:

Я пытаюсь реализовать добавление новой части информации вверху, когда пользователь прокручивает вверх (чтобы просмотреть историю чата) без каких-либо переходов, как в Telegram, Whatsup и так далее

Вот мой метод

 private var toItem: NSIndexPath?

private func addMoreCells () {
    if collectionView.contentOffset.y <= 0 {
        guard let userChatUid = user?.chatUid else { return }
        guard let ownChatUid = UsersManager.sharedInstance.currentChatUID() else { return }
        guard let offset = conversation?.messages.count else { return }


        ConversationsManager.sharedInstance.getConversationsWithMoreMessagesFor(ownChatUid, recipient: userChatUid, offset: offset - 1, successHandler: { [weak weakSelf = self] (conversations) in
            dispatch_async(dispatch_get_main_queue()) {
                if let messagesFromServer = conversations.first?.messages, var messages = weakSelf?.conversation?.messages {

                    for message in messagesFromServer {
                        if !messages.contains(message) {
                            messages.append(message)
                        }
                    }

                    messages = messages.sort({$0.time?.compare($1.time!) == .OrderedAscending})

                    weakSelf?.conversation?.messages = messages
                    weakSelf?.collectionView.reloadData()
                    weakSelf?.toItem = NSIndexPath(forItem: (messages.count - messagesFromServer.count), inSection: 0)
                    if let item = weakSelf?.toItem{
                        weakSelf?.collectionView.scrollToItemAtIndexPath(item, atScrollPosition: .Top, animated: false)
                    }

                }
            }

            }, failHandler: { (error) in
                print(error)
        })
    }
}
  

который запускается из

 func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    addMoreCells()
}
  

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

Но я ожидаю, что оно должно вернуться к значению messages.count - messagesFromServer.count . В xCode я вижу, что цифры меняются каждый раз, когда я прокручиваю, но scrollToItemAtIndexPath не работает должным образом

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

Кто-нибудь может знать, в чем проблема? Потому что я не могу найти решения, чтобы это исправить.

Ответ №1:

Я решил эту проблему следующим образом:

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

 weakSelf?.collectionView.reloadData()

guard let previousContentSize = weakSelf?.collectionView.contentSize else { return }

weakSelf?.collectionView.collectionViewLayout.invalidateLayout()
weakSelf?.collectionView.collectionViewLayout.prepareLayout()
weakSelf?.collectionView.layoutIfNeeded()

guard let newContentSize = weakSelf?.collectionView.contentSize else { return }

print("previous Content Size (previousContentSize) and new Content Size (newContentSize)")

let contentOffset = newContentSize.height - previousContentSize.height
weakSelf?.collectionView.setContentOffset(CGPoint(x:  0.0, y: contentOffset), animated: false)
  

Я отлично работаю, как и следовало ожидать.