Odd behavior re: -windowWillReturnUndoManager:
Odd behavior re: -windowWillReturnUndoManager:
- Subject: Odd behavior re: -windowWillReturnUndoManager:
- From: Matthew LeRoy <email@hidden>
- Date: Thu, 16 Jan 2014 19:51:32 +0000
- Thread-topic: Odd behavior re: -windowWillReturnUndoManager:
Good morning,
I’m implementing a floating document inspector for my document-based app, and am having trouble getting undo/redo working reliably when the inspector is the key window. Specifically, NSWindowDelegate’s -windowWillReturnUndoManager: doesn’t seem to be doing the trick like everything else I’ve read on this topic says it should — at least not reliably. I am developing with Xcode 5.0.2 on Mavericks 10.9.1, targeting the Mountain Lion 10.8 SDK.
The inspector window is an NSPanel in its own XIB file. File’s Owner is an NSWindowController subclass, MTInspectorPanelController. The controller is the panel’s delegate. The controller tracks the current document by KVO observing mainWindow.windowController.document on NSApp, the same way as is done in the TextEdit sample app. This all seems to work just fine.
When I realized that my undo/redo menu items weren’t active when the inspector panel was key, I went in search of a solution and found [NSWindowDelegate windowWillReturnUndoManager:]. All signs pointed to implementing this function in the inspector panel controller (the panel’s delegate) to return the undo manager for the current document, so thats what I did:
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
if (window == [self window])
{
return [[self inspectedDocument] undoManager];
}
return nil;
}
Unfortunately, this only seems to partially work. There are two issues I’m running into:
1. The application supports window restoration, and if the inspector panel was open when the app last quit (and is thus restored when the app runs next) *and* I have full keyboard access disabled (which causes one of the text fields in the inspector panel to be first responder when the app launches), then the undo/redo menu items will never be enabled when the inspector panel is key (although they work just fine if the main document window is key). On the other hand, if the inspector panel is closed when the app quits (and is thus not restored on next run), *or* full keyboard access is enabled (which causes one of the buttons in the NSSegmentedControl to be first responder in the inspector panel when the app launches) then the undo/redo menu items will work when the inspector panel is key (once it is reopened).
I suspect this has something to do with the fact that when the inspector is being restored on app startup with full keyboard access disabled, -windowWillReturnUndoManager: gets called on the inspector panel controller early during window restoration when there is not yet an active document, and thus the method returns nil. After that, windowWillReturnUndoManager: never gets called again — not when the inspector becomes key, not when I open the Edit menu, never. On the other hand, when the inspector panel is not open (and thus not restored during app startup), or when full keyboard access is enabled, -windowWillReturnUndoManager: doesn’t get called on the inspector panel controller during app startup. In fact, it doesn’t get called until I either open the Edit menu while the inspector panel is key, or one of the text fields in the inspector panel becomes first responder. At that point all of the application’s open documents have been fully loaded and the inspector knows which one is active, so the method has an undo manager to return rather than nil. It seems that if -windowWillReturnUndoManager: returns nil, then the method never gets called again.
2. In the case where the inspector was *not* open when the app launches or full keyboard access is enabled and thus undo/redo is working when the inspector is key, it sometimes does not correctly switch to the undo manager for the current document. For example, if I have multiple clean documents open and then make several undoable edits in one document and then switch to a different (clean) document and then make the inspector key, occasionally — and this only happens sometimes and I can’t seem to reliably replicate it — the Edit menu will still show the Undo/Redo menu items corresponding to the initial dirty document. I can even execute those menu items and watch the changes take place in the document window for the dirty document, even though it is not the main window and the inspector (which is key) is correctly tracking the document whose window is main. If I make the main (clean) document’s window key, the undo/redo menu items go back to being disabled (which is correct since there are no actions on the undo/redo stack for that document). With a log statement in windowWillReturnUndoManager:, I can see that on the occasions when this happens, windowWillReturnUndoManager: is not getting called when the Edit menu is opened, as it usually does.
I’ve verified that both of these behaviors exist on a coworker’s machine as well, which is running Xcode 5.0.2 on Mountain Lion 10.8.5.
Any clues? Both of these sound like bugs to me, but I’m open to whatever suggestions for workarounds or troubleshooting anyone may have before I log a radar.
Thanks!
Matt
_______________________________________________
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