NSTableView.setNeedsDisplay () не перерисовывается только на вложенных изменениях Formatter - PullRequest
0 голосов
/ 22 апреля 2019

Я использую NSTableView на основе представления со столбцом, который показывает даты, а представления ячеек таблицы используют общий DateFormatter.

let view: NSTableCellView? = tableView.makeView(withIdentifier: column.identifier, owner: self) as! NSTableCellView?
let entry = (logController.arrangedObjects as! [LogEntry])[row]
    switch column.identifier {
    case columnDateKey:
        view?.textField?.formatter = sharedDateFormatter
        view?.textField?.objectValue = entry.date

Приложение имеет пользовательские предпочтения для выбора формата даты и ранее код

tableView.setNeedsDisplay(tableView.rect(ofColumn: tableView.column(withIdentifier: columnDateKey)))

обновит столбец с новым форматом даты.

С macOS Mojave этого не происходит. Расследование показывает, что, хотя drawRect: вызывается для базового TableView, в tableView не выполняется никаких вызовов (: viewFor: row :) для получения новых значений для представлений ячеек таблицы. Вызов tableView.reloadData (forRowIndexes: columnIndexes :) приводит к вызовам tableView (: viewFor: row :), но отображение не обновляется (хотя это происходит для tableView.reloadData ()).

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

Это поведение изменилось с появлением Мохаве, и мне трудно поверить, что никто другой не сообщил об этом, и поэтому я начинаю сомневаться в моем исходном коде. Я что-то упустил?

Следующий тестовый код демонстрирует проблему: сообщение «Просмотр запрошенного» не печатается для вариантов setNeedsDisplay, а отображение перерисовывается только для reloadData ()

styleButton - флажок для переключения формата чисел, а refreshButton - кнопка действия для запроса перерисовки

Установка значения на случайное значение приведет к ожидаемому поведению перерисовки

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var table: NSTableView!
    @IBOutlet weak var styleButton: NSButton!
    @IBOutlet weak var refreshButton: NSButton!
    @IBOutlet weak var testView: NSView!

    let numberFormatter = NumberFormatter()

    func applicationWillFinishLaunching(_ notification: Notification) {
    numberFormatter.numberStyle = symbolButton.state == NSControl.StateValue.on ? NumberFormatter.Style.decimal : NumberFormatter.Style.none
    }

    @IBAction func refresh(sender: Any?) {
        numberFormatter.numberStyle = styleButton.state == NSControl.StateValue.on ? NumberFormatter.Style.decimal : NumberFormatter.Style.none
        table.setNeedsDisplay(table.rect(ofColumn: 0))
        // table.needsDisplay = true
        // table.reloadData(forRowIndexes: IndexSet(integersIn: 0..<table.numberOfRows), columnIndexes:[0])
        // table.reloadData()
    }
}

extension AppDelegate: NSTableViewDataSource {
    func numberOfRows(in tableView: NSTableView) -> Int {
        if tableView == table {
            return 40
        }
        return 0
    }
}

extension AppDelegate: NSTableViewDelegate {
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        print("View requested")
        guard tableColumn != nil else {
            return nil
        }
        let column = tableColumn!
        if tableView == table {
            let view: NSTableCellView? = tableView.makeView(withIdentifier: column.identifier, owner: self) as! NSTableCellView?
            view?.textField?.formatter = numberFormatter
            view?.textField?.objectValue = 123.456
            return view
        }
        return nil
    }
}

1 Ответ

0 голосов
/ 25 апреля 2019

Неправильное использование view.setNeedsDisplay для автоматического обновления подпредставлений. Это не так (хотя раньше это так и казалось) - см. Комментарий Виллекса выше

...