Re: Field editor undo vs document dirty
Re: Field editor undo vs document dirty
- Subject: Re: Field editor undo vs document dirty
- From: Quincey Morris <email@hidden>
- Date: Tue, 7 Apr 2009 15:49:25 -0700
On Apr 7, 2009, at 08:06, Adam R. Maxwell wrote:
Have your controller object implement the NSEditor protocol. Send
the document objectDidBeginEditing:/objectDidEndEditing: at the
appropriate times (maybe using text delegate notifications), and it
will send you commitEditing/discardEditing et al. as needed.
NSDocument says it handles this in the header, even though it
doesn't explicitly conform to NSEditorRegistration, so I believe
this will keep working.
1. Thanks, this is indeed most of the answer. In this application I
was using a NSWindowController subclass as the XIB's owner (instead of
the NSDocument subclass), and NSWindowController doesn't have the
smarts that NSDocument does. So I added this to the NSWindowController
subclass:
- (void) objectDidBeginEditing: (id) editor {
[self.document objectDidBeginEditing: editor];
}
- (void) objectDidEndEditing: (id) editor {
[self.document objectDidEndEditing: editor];
}
2. But that's not the whole story. My text fields were bound via a
NSObjectController, and the object controller did *not* invoke
objectDidBeginEditing: until I changed the content outlet connection
to a content object binding. Apparently this whole editor registration
scheme works only in the context of bindings. (Presumably this would
not have been an issue if I'd omitted the NSObjectController and bound
the text fields directly to the NSWindowController subclass.)
3. Next, I found that if I try to close the document window with an
edit in progress but without saving changes, NSDocument gets stuck in
an endless loop in _discardEditing (called from [NSDocument close]
called from windowDidClose:. I speculate that either the text field
got garbage collected before it had a chance to send
objectDidEndEditing:, or it couldn't send it because the chain of
bindings had already been broken, so I added:
- (void) windowWillClose: (NSNotification*) notification {
[objectController discardEditing];
}
to the window controller subclass and that seemed to take care of it.
4. The one remaining problem occurs if there's a validation error on
the uncommitted text field during a save (i.e. validate<Key> returns
NO for the property the text field is bound to). The error sheet
displayed with the correct error message, but clicking OK causes the
application to crash with EXC_BAD_ACCESS. The BT varies a bit, but
here's an example:
#0 0x9342a6a0 in objc_msgSend
#1 0x92d08020 in -[NSDocument(NSEditorRegistration)
_editor:didCommit:withContext:]
#2 0x92ef603e in _NSSendCommitEditingSelector
#3 0x92cdcd54 in -[NSController
_controllerEditor:didCommit:contextInfo:]
#4 0x92ef603e in _NSSendCommitEditingSelector
#5 0x92ed5e3e in -[NSValueBinder _commitEditingOtherCallback:]
#6 0x92ef619c in _NSSendContextInfoCallbackSelector
#7 0x92ed63f2 in -[NSValueBinder
_didPresentDiscardEditingSheetWithRecovery:contextInfo:]
#8 0x92c0eb84 in -[NSApplication(NSErrorPresentation)
_errorAlert:wasPresentedWithResult:inContext:]
#9 0x92b3742d in -[NSAlert didEndAlert:returnCode:contextInfo:]
#10 0x929db233 in -[NSApplication endSheet:returnCode:]
#11 0x92b373c0 in -[NSAlert buttonPressed:]
#12 0x9299953b in -[NSApplication sendAction:to:from:]
#13 0x92999478 in -[NSControl sendAction:to:]
#14 0x929992fe in -[NSCell _sendActionFrom:]
#15 0x92a735ff in -[NSButtonCell performClick:]
#16 0x92a46abd in -[NSButton performKeyEquivalent:]
#17 0x92a4692a in -[NSControl _performKeyEquivalent:conditionally:]
#18 0x92a467f6 in -[NSView performKeyEquivalent:]
#19 0x92a467f6 in -[NSView performKeyEquivalent:]
#20 0x92a4655f in -[NSWindow performKeyEquivalent:]
#21 0x92ba7e6e in -[NSWindow keyDown:]
#22 0x92996ddd in -[NSWindow sendEvent:]
#23 0x92962d49 in -[NSApplication sendEvent:]
#24 0x00011473 in -[BLSApplication sendEvent:] at BLSApplication.m:24
#25 0x928c069f in -[NSApplication run]
#26 0x9288d8a4 in NSApplicationMain
#27 0x00002de4 in main at main.m:13
and here's another:
#0 0x9477d13f in -[NSMethodSignature _argInfo:]
#1 0x9477f3d5 in -[NSInvocation invoke]
#2 0x93b8822e in __NSFireDelayedPerform
#3 0x94700b25 in CFRunLoopRunSpecific
#4 0x94700cd8 in CFRunLoopRunInMode
#5 0x917da2c0 in RunCurrentEventLoopInMode
#6 0x917da012 in ReceiveNextEventCommon
#7 0x917d9f4d in BlockUntilNextEventMatchingListInMode
#8 0x928c7d7d in _DPSNextEvent
#9 0x928c7630 in -[NSApplication
nextEventMatchingMask:untilDate:inMode:dequeue:]
#10 0x928c066b in -[NSApplication run]
#11 0x9288d8a4 in NSApplicationMain
#12 0x00002de4 in main at main.m:13
In every case I've seen, the instruction that fails is trying to
dereference a nil pointer in one of the registers.
I suspect that it's a similar problem to case #3, that something the
deferred error handling is relying on got released because the window
or document is closing underneath it.
If anyone has any comments/suggestions about #3 or #4, I'd glad to
hear them.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden