Скрытые ячейки TableViews за видимыми ячейками, которые не представлены моделями - PullRequest
4 голосов
/ 17 мая 2019

В настоящее время я создаю приложение чата для клиента. Чат реализован с использованием UITableView с пользовательскими ячейками. Текстовое сообщение от бота строится как пользовательский UITableViewCell с UITextView (потому что он должен быть кликабельным для ссылок, в противном случае я бы использовал UILabel), обернутым внутри контейнера UIView, чтобы нарисовать пузырь вокруг него. Также этот вид контейнера имеет тень, чтобы понравиться дизайнеру: P

Каждый раз при получении нового сообщения от бота это сообщение задерживается на долю времени, чтобы пользователь мог прочитать сообщение раньше. В это время так называемый WaitingMessageTableViewCell отображается в индексе, в который будет поступать новая ячейка. По истечении времени WaitingMessageTableViewCell удаляется из модели, а затем из tableView и вставляется новая ячейка.

            tableView.beginUpdates()
            if let insertRows = insertRows {
                tableView.insertRows(at: insertRows, with: .none)
            }
            if let deleteRows = deleteRows {
                tableView.deleteRows(at: deleteRows, with: .none)
            }
            if let reloadRows = reloadRows {
                tableView.reloadRows(at: reloadRows, with: .none)
            }
            tableView.endUpdates()

Проблема была найдена дизайнером, который сказал, что когда WaitingMessageTableViewCell собирается появиться, тень ячейки до того, как становится сильнее в течение некоторого времени. Я отладил в нем и обнаружил, что перед вставкой WaitingMessageTableViewCell он появляется за ячейкой, что для меня не имеет смысла (это механизм повторного использования ?!) Теперь самое странное: я использовал встроенный в Xcode UI Analyzer и увидел, что за видимыми ячейками есть скрытые ячейки, которые не представлены моделями.

(lldb) po tableView.subviews
▿ 5 elements
  ▿ 0 : <CHAT.WaitingMessageTableViewCell: 0x7fdef286a600; baseClass = UITableViewCell; frame = (0 395.5; 375 40); hidden = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x600003952d80>>
  ▿ 1 : <CHAT.AgentMessageTableViewCell: 0x7fdef2861e00; baseClass = UITableViewCell; frame = (0 294.5; 375 101); hidden = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x6000039bf160>>
  ▿ 2 : <CHAT.AgentMessageTableViewCell: 0x7fdef3897600; baseClass = UITableViewCell; frame = (0 395.5; 375 101.5); opaque = NO; autoresize = W; layer = <CALayer: 0x6000039aba20>>
  ▿ 3 : <CHAT.AgentMessageTableViewCell: 0x7fdef382e200; baseClass = UITableViewCell; frame = (0 294.5; 375 101); opaque = NO; autoresize = W; layer = <CALayer: 0x600003955a00>>
  ▿ 4 : <CHAT.WelcomeTableViewCell: 0x7fdef2882c00; baseClass = UITableViewCell; frame = (0 0; 375 294.5); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x600003951160>>
(lldb) po tableView.visibleCells
▿ 3 elements
  ▿ 0 : <CHAT.WelcomeTableViewCell: 0x7fdef2882c00; baseClass = UITableViewCell; frame = (0 0; 375 294.5); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x600003951160>>
  ▿ 1 : <CHAT.AgentMessageTableViewCell: 0x7fdef382e200; baseClass = UITableViewCell; frame = (0 294.5; 375 101); opaque = NO; autoresize = W; layer = <CALayer: 0x600003955a00>>
  ▿ 2 : <CHAT.AgentMessageTableViewCell: 0x7fdef3897600; baseClass = UITableViewCell; frame = (0 395.5; 375 101.5); opaque = NO; autoresize = W; layer = <CALayer: 0x6000039aba20>>
(lldb) po AssistantDataManager.shared.cellModels
▿ 3 elements
  ▿ 0 : <WelcomeCellModel: 0x600002c80740>
  ▿ 1 : <SimpleAgentTextCellModel: 0x600001af0050>
  ▿ 2 : <AskQuestionCellModel: 0x600002c80400>

Также вот мой метод cellForRows:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        guard indexPath.row < AssistantDataManager.shared.cellModels.count else {
            return UITableViewCell()
        }
        let cellModel = AssistantDataManager.shared.cellModels[indexPath.row]

        if let cell = tableView.dequeueReusableCell(withIdentifier: cellModel.cellReuseIdentifier) as? AssistantActionBaseTableViewCell {
            //Quickfix for stronger shadow
            cell.backgroundColor = Colors.tableViewBackgroundColor

            cell.configure(with: cellModel)
            if let topContraint = cell.topContraint {
                topContraint.constant = calculateTopContraintSpacing(for: indexPath)
            }

            if let bottomContraint = cell.bottomContraint {
                bottomContraint.constant = 0
            }

            cell.selectionStyle = .none
            return cell
        }
        return UITableViewCell()
    }

Кто-нибудь может мне сказать, почему новый вставленный WaitingMessageTableViewCell сначала находится за ячейкой выше, а затем перемещается вниз, и почему мой tableView заполняется гораздо большим количеством ячеек, чем должно быть?

Большое спасибо заранее.

1 Ответ

0 голосов
/ 21 мая 2019

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

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

tableView.performBatchUpdates({
    if let insertRows = insertRows {
        tableView.insertRows(at: insertRows, with: .none)
    }
    if let deleteRows = deleteRows {
        tableView.deleteRows(at: deleteRows, with: .none)
    }

}) { (finished) in
    self.tableView.performBatchUpdates({
        if let reloadRows = reloadRows {
            self.tableView.reloadRows(at: reloadRows, with: .none)
        }
    }, completion: nil)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...