Update: I think there's a relationship between this window's level and this problem: This never happened when this window.level
was set to .normal
, but when it was set to background wallpaper level.
I met a bizarre phenomenon in NSTableView behavior when I tried calling reloadData()
on it. After calling reloadData()
, my NSTableView correctly displayed new table cells according to the data source, but what was weird is old cells weren't completely "removed" but they kind of left their "ghost trail" or "mark" in the table view.
See the image below:
I have exhausted all methods I could think of, including prepareForReuse
, I even went to the extreme thing of removing all cells from superview (NSTableView) before reloading data, and set cell.identifier = ""
to force table view to create a brand new cell every reload, but that didn't work either.
My code is very simple as below
Controller code:
// TodoListTableViewController.swift
eventStore.fetchReminders(matching: predicateIncompleteReminders) { reminders in
self.reminders = reminders
DispatchQueue.main.async { [self] in
todoListTableView.reloadData()
}
}
// still in TodoListTableViewController.swift
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let reminder = reminders[row]
let itemCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: CellViewIdentifierSet.TodoItemCellView.rawValue), owner: self) as! TodoItemCellView
itemCell.todoItemTextField.stringValue = reminder.title
itemCell.todoColorTextField.textColor = reminder.calendar.color
if let date = reminder.dueDateComponents?.date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
itemCell.todoStartTimeTextField.stringValue = dateFormatter.string(from: date)
} else {
itemCell.todoStartTimeTextField.stringValue = ""
}
return itemCell
}
TodoItemCellView code:
import Cocoa
class TodoItemCellView: NSTableCellView {
@IBOutlet var todoColorTextField: NSTextField!
@IBOutlet var todoItemTextField: NSTextField!
@IBOutlet var todoStartTimeTextField: NSTextField!
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
todoItemTextField.maximumNumberOfLines = 2
}
override func prepareForReuse() {
super.prepareForReuse()
todoItemTextField.stringValue = ""
todoStartTimeTextField.stringValue = ""
}
}
I'm pretty confident that logically nothing can be wrong. I also double checked that only one table view in my storyboard and no double stacked views.
I'm running the app on my MacBook Pro (mid 2015).
Edit: I did a view hierarchy debugging session. The view hierarchy was like this:
However, what my app displayed looked like this (notice the blurred trail)
Is it safe to assume that my MacBook Pro 2015 has a poor-quality display that can't properly refresh the content? And won't this behavior show up on other people's computers?