У меня есть NSTableView, который может менять местами представления разных ячеек на основе значений данных для строки. Когда модель изменится, я перезагружу таблицу, и делегат таблицы предоставит правильное представление ячейки таблицы для новых данных.
В таблице используется автоматическое расположение для представлений ячеек Все виды ячеек изначально загружаются нормально. Обновляя таблицу после смены модели, я получаю разные результаты в зависимости от того, звоню я reloadData()
или reloadData(forRowIndexes:columnIndexes)
. При использовании reloadData()
представление ячейки загружается, и автоматическое расположение работает нормально. Если я использую reloadData(forRowIndexes:columnIndexes)
, autolayout дает совершенно другие, неожиданные результаты.
Я создал пример проекта, чтобы продемонстрировать проблему.
Здесь - изображение настройки проекта, включая ограничения, установленные для представлений ячейки таблицы. Существует два шаблона строк, один с синим представлением (четные строки), другой с зеленым (нечетные строки), которые должны охватывать ширину таблицы (без небольшого отступа). Контроллер предоставляет вид ячеек:
class TableController: NSObject {
@IBOutlet weak var tableView: NSTableView!
var colorData = [1, 0, 1, 0]
@IBAction func swapLine(_ sender: Any) {
colorData[1] = (colorData[1] + 1) % 2
// tableView.reloadData()
tableView.reloadData(forRowIndexes: [1], columnIndexes: [0])
}
}
extension TableController: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return colorData.count
}
}
extension TableController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cellId = (colorData[row]) % 2 == 0 ? "EvenCell" : "OddCell"
return tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(cellId), owner: self)
}
}
Кнопка в интерфейсе просто меняет данные для строки 1 и перезагружает данные. Первоначальный вид выглядит как это (чередуются зеленые и синие линии). Если вы используете reloadData()
, это выглядит как this (строка 1 изменена с синего на зеленый). Но если вы используете reloadData(withRowIndexes:columnIndexes:)
, вид ячеек сжимается до 40 точек шириной, а не 480, как в других. Вот отладчик представления, показывающий представление ячейки с неправильным размером и показывающий неоднозначные ограничения ширины (этого не происходит при использовании reloadData()
).
В документации упоминается, что представление строки повторно используется с reloadData(forRowIndexes:columnIndexes:)
, но не с reloadData()
, что я проверял. Я полагаю, что повторное использование представления строк вызывает проблемы с автопоставкой, но я не могу найти никакой связи. Ничего не нашлось в SO, заметках о выпуске AppKit, видео WWDC, поиске в Google или в том, что я постучал по столу. Был бы действительно благодарен за помощь.
Обновление:
Вот код для ColorView:
class ColorView: NSView {
@IBInspectable var intrinsicHeight: CGFloat = 20
@IBInspectable var color: NSColor = NSColor.blue
override var intrinsicContentSize: NSSize {
return NSSize(width: NSView.noIntrinsicMetric, height: intrinsicHeight)
}
override func draw(_ dirtyRect: NSRect) {
color.setFill()
dirtyRect.fill()
}
}