问题
I'm running into the strangest issue with my NSOutlineView
:
- Everything is set up in a storyboard, i.e. the outline view and two
NSTableCellView
s - The two cell views are mostly the same, only one shows an icon, the other one doesn't
- I can begin editing an item (row) by pressing the
Return
key, i.e. theNSTextField
that is part of myNSTableCellView
enters into edit mode. This is the default behavior and works fine so far.
However:
- After editing ends and the item was changed, I use the second table view cell from the storyboard (the one without an icon).
- Now entering "edit" mode by pressing the
Return
key does not work anymore! The app beeps and that's it.
Both cell views on their own are editable when they are initially loaded. I confirmed this. The problem occurs when an item is first shown with one table cell view, then with the other one (and vice versa).
Editing an item multiple times works fine then the underlying NSTableCellView
does not change. Can anybody shine some light at what is going on here?
To reproduce:
- New Xcode project, Mac app
- Add an
NSOutlineView
to your view controller with one column - Add two table view cells, "One", "Two" (identifiers)
- Use the code below
Steps:
- Run the app, select the second item
- Press "Return", type "green", "Return"
- Press "Return" again to enter edit mode a second time
Expected:
- Cell should become editable again
Actual:
- App beeps
Code:
import Cocoa
class ViewController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate, NSTextFieldDelegate {
@IBOutlet var outlineView: NSOutlineView!
private var items = ["One", "Two"]
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
return item == nil ? items.count : 0
}
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
return items[index]
}
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
return false
}
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
guard let item = item as? String else { return nil }
NSLog("Vending cell view for: \(item)")
let identifier = item.contains("green") ? "Two" : "One"
if let view = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: identifier), owner: nil) as? NSTableCellView
{
view.textField?.stringValue = item
view.textField?.delegate = self
return view
}
return nil
}
func controlTextDidEndEditing(_ obj: Notification) {
NSLog("Did end editing")
guard
let textField = obj.object as? NSTextField,
let item = outlineView.item(atRow: outlineView.row(for: textField)) as? String else {
return
}
NSLog("Reloading item: \(item)")
let row = outlineView.row(for: textField)
items[row] = textField.stringValue
outlineView.reloadItem(item)
}
}
UPDATE:
I found a workaround, but this looks like a bug to me. If I call outlineView.reloadData(forRowIndexes:columnIndexes:)
right after reloadItem()
, the problem does not occur.
Doesn't work (problem occurs):
outlineView.reloadItem(item)
Doesn't work (outlineView's data model not updated, shows old value):
outlineView.reloadData(forRowIndexes: IndexSet([row]), columnIndexes: IndexSet([0]))
This finally works:
outlineView.reloadItem(item)
outlineView.reloadData(forRowIndexes: IndexSet([row]), columnIndexes: IndexSet([0]))
The above causes the cell view to be requested a second time.
来源:https://stackoverflow.com/questions/60397648/nsoutlineview-row-not-editable-by-return-key-anymore-after-reloading-a-differe