I am having trouble understanding how NSUndoManager captures values when the values are reference types. Whenever try to use the undoManager, the values don't undo.
Note: I need to support macOS 10.10, and I am using Swift 3 and XCode 8
Here I save the state of the ID numbers, reset them all to -1, and then try to undo. The result is that they are all still -1.
import Cocoa
class Person: NSObject {
var id: ID
init(withIDNumber idNumber: Int) {
self.id = ID(idNumber)
}
}
class ID: NSObject {
var number: Int
init(_ number: Int) {
self.number = number
}
}
ViewController... {
@IBAction func setIDsToNegative1(_ sender: NSButton) {
var savedIDs: [ID] = []
for person in people {
savedIDs.append(person.id)
}
undoManager?.registerUndo(withTarget: self, selector:#selector(undo(savedIDs:)), object: savedIDs)
for person in people {
person.id.number = -1
}
}
func undo(savedIDs: [ID]) {
for id in savedIDs {
print(id.number)
}
//Prints -1, -1, -1
}
}
To prove to myself that it was a problem capturing values, instead of saving the ID objects themselves, I stored the Int values that they contain. It worked perfectly as the Ints are value types.
Then I read some more about closure capturing and tried this.
undoManager?.registerUndo(withTarget: self, handler: { [saved = savedIDs]
(self) -> () in
self.undo(savedIDs: saved)
})
Same problem, all still -1.