cocoa - Invocation-based Undo Manager in Swift -
this question has answer here:
i'm having trouble adopting more complex invocation-based approach undo registration in swift (based on nshipster article here. apple's docs still have sample code in objective-c, , semantics different invocation setup).
my nsdocument
subclass document
has following method operates on model objects, wish make undoable:
func rename(object: any, newname: string) { // protocol requires implementing: // var name: string { set } // guard var namedobject = object as? editorhierarchydisplayable else { return } // register undo: let undocontroller = undomanager?.prepare(withinvocationtarget: self) as? document undocontroller?.rename(object: namedobject, to: namedobject.name) undomanager?.setactionname("rename \(namedobject.localizedclassname)") // perform change: namedobject.name = newname }
what have found out undocontroller
above nil
, becuase atempted cast document
fails. if remove cast (and comment out call undocontroller.rename(...
), prepare(withinvocationtarget:)
returns folowing object:
(lldb) print undocontroller (any?) $r0 = { payload_data_0 = 0x00006080000398a0 payload_data_1 = 0x0000000000000000 payload_data_2 = 0x0000000000000000 instance_type = 0x000060800024f0d8 } (lldb) print undocontroller.debugdescription (string) $r1 = "optional(nsundomanagerproxy)" (lldb)
what missing?
i think basic confusion prepare(withinvocationtarget:)
returns proxy object (that happens undo manager itself, that's implementation detail). idea send proxy object same message(s) send undo action, instead of executing them (because it's not actual object), internally captures invocations , saves them later.
so code should start out this:
let selfproxy: = undomanager?.prepare(withinvocationtarget: self)
this works great in objective-c because "catchall" type (id) has lax type checking. equivalent any
class in swift more stringent , not lend same technique, if @ all.
see using nsundomanager , .prepare(withinvocationtarget:) in swift 3
Comments
Post a Comment