I have followed this tutorial and successfully bind my NSTableView
to a core data entity.
The table is a view based cell and is populated perfectly from the core data entity.
I have +
and -
buttons bind to the NSArrayController
. When I press the plus button a new record is added to core data and appear on the table, when I select an entry and press the minus sign, that is removed from the database. For that matter I have override this code for the add/remove keys.
@IBAction override func add(_ sender: (Any)?) {
let newApp = self.newObject() as AnyObject
newApp.setValue("New Entry", forKey: "name")
self.addObject(newApp as Any)
}
@IBAction override func remove(_ sender: (Any)?) {
// Do certain stuff before removing all selected rows
self.remove(atArrangedObjectIndexes: self.tableView!.selectedRowIndexes)
}
I made the table view cells editable. When the plus sign button is pressed a new entry is created and appear on the table with the text "New Entry". This new entry creates a core data record. Let's call it record 1
.
Now I want the user to edit the entry with the name they want.
So I select the new cell and press enter. The cell is now on edit mode. I type the new name I want to that cell, that will be passed to the core data entity.
I type, for example, BONOBO and press ENTER.
This table must contain just unique names. So, as soon as ENTER is pressed and the cell ends editing, I want to check core data to see if the name BONOBO is already taken and if it is, reject the name and tell the user to provide a new name.
This is the problem: as soon as I press ENTER, record 1
changes its name instantly from New Entry
to BONOBO
, before I can check if the entry already exists on the database, meaning that any check I do, will always tell me that the record exists. In fact the record exists in memory because the context was not saved yet.
I am intercepting the enter press by setting the delegate of all cells to a class and using its delegate method controlTextDidEndEditing(_ obj: Notification)
.
I have also tried to set an action for the textfields but the problem is the same.
How do I intercept it before the core data change happens?
The trick here is to leverage Key-Value Coding's built-in validation methods. See Object Validation.
I've never done this with a managed object, but the process seems to be the same as with regular KVC validation. You want to implement a method with the name:
validate<Key>:error:
... Where 'Key' is the name of the parameter you're trying to validate. This takes in a pointer for the value you want to validate, and another for an NSError object. Inside the method you test whether the passed-in value is acceptable. You can return true to accept it, modify the value and return true to accept a revised version, or return false to reject it outright (modifying the error object to have something to send back to the user).