Как обновить высоту табличного представления с собственным размером?

Если я поместил пользовательское представление в ячейку, как я могу уведомить табличное представление об обновлении высоты ячейки, если высота моего пользовательского представления изменилась? Я пробовал invalidateIntrinsicContentSize, но это не сработало. ReloadData работает, но я сомневаюсь, что использую

self.superview?.superview?.superview as! UITableView).reloadData()

является хорошей реализацией. Я видел аналогичный вопрос здесь но это все о представлении из стандартной библиотеки. И это и это не имеет ответа.


person Nick Allen    schedule 26.09.2015    source источник


Ответы (1)


Вы думаете в правильном направлении. Однако есть две проблемы с вашим подходом:

  1. reloadData перезагружает все табличное представление и не анимирует изменение.
  2. Движение вверх по цепочке суперпредставлений обязательно прервется, когда Apple изменит UITableView иерархию представлений. Они делали это раньше, так что они могут сделать это снова.

Чтобы исправить первую проблему, вы должны вместо этого вызвать reloadRowsAtIndexPaths:withRowAnimation:. Это перезагружает только те ячейки, которые вы указываете в массиве indexPath. Таким образом, вы передаете ему массив, который содержит только indexPath вашей ячейки.

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

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

class YourCustomTableViewCell: UITableViewCell {
    var resizeClosure: (() -> Void)?
    ...

И вы устанавливаете это закрытие в своем UITableViewControllerDataSource, когда удаляете ячейку из очереди:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("YourCustomCellIdentifier", forIndexPath: indexPath)
        if let customCell = cell as? YourCustomTableViewCell {
            customCell.resizeClosure = { [weak cell, weak tableView] in
                if let currentIndexPath = tableView?.indexPathForCell(cell!) {
                    tableView?.reloadRowsAtIndexPaths([currentIndexPath], withRowAnimation: .Automatic)
                }
            }
        }

        return cell
    }

Просто убедитесь, что вы добавили tableView в список захвата замыкания, чтобы избежать сильного цикла ссылок. Это делается путем добавления [weak tableView] к замыканию.

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

func someFunctionThatChangesTheHeight() {
   // change the height
   resizeClosure?()
}
person joern    schedule 27.09.2015
comment
Я думал об этом однажды. Но indexPath можно изменить, если мы удалим ячейки до этого, поэтому в моем случае я бы напрямую вызывал beginUpdate и endUpdate tableview (всего пять ячеек). И я считаю, что вызов invalidateIntrinsicContentSize должен обновить высоту ячейки для таблицы с собственным размером, поэтому Apple должна исправить эту ошибку. - person Nick Allen; 29.09.2015
comment
О, да, вы совершенно правы, indexPath должно быть получено при выполнении закрытия (чтобы принять во внимание удаленные и новые ячейки). Я отредактировал свой ответ. Я согласен, что Apple должна найти здесь надежное решение. - person joern; 29.09.2015