Correct way to have nil undo manager in Core Data document?
Correct way to have nil undo manager in Core Data document?
- Subject: Correct way to have nil undo manager in Core Data document?
- From: Jerry Krinock <email@hidden>
- Date: Sat, 29 Aug 2009 13:01:57 -0700
From the Core Data Programming Guide:
"If you do not intend to use Core Data's undo functionality, you can
reduce your application's resource requirements by setting the
context’s undo manager to nil. This may be especially beneficial for
background worker threads..."
Well, I've got a background worker process which opens an
NSPersistenDocument. Since it has no "undo" capability, I want to set
it to nil as recommended. (I have other reasons for not wanting an
undo manager scurrying around.) But the document doesn't like having
nil undo manager. When I ask for it later, it creates one for itself,
and sets its managed object context to have the same one.
This is easily demonstrated by adding the following method to
DepartmentAndEmployees project, in the implementation of MyDocument:
- (id)init {
self = [super init] ;
if (self) {
// Set both doc's and moc's undo manager to nil
[[self managedObjectContext] setUndoManager:nil] ;
[self setUndoManager:nil] ;
// Get and log them
NSLog(@"1: moc's undoManager = %@", [[self
managedObjectContext] undoManager]) ;
NSLog(@"2: doc's undoManager = %@", [self undoManager]) ;
NSLog(@"3: moc's undoManager = %@", [[self
managedObjectContext] undoManager]) ;
}
return self ;
}
Here is the debugger Log Output, with breakpoint set at -
[NSManagedObjectContext setUndoManager:]
Running…
(gdb) continue
(gdb) continue
(gdb) continue
(gdb) continue
Test[61463:813] 1: moc's undoManager = (null) ## This is good.
(gdb) p/a *(int *)($esp+8)
$1 = 0x161a80
(gdb) continue
Test[61463:813] 2: doc's undoManager = <NSUndoManager: 0x161a80> ##
Arghh!!
Test[61463:813] 3: moc's undoManager = <NSUndoManager: 0x161a80> ##
Arghh!!
Here is the call stack at the last break. I typed the p/a command
when viewing #1.
#0 0x92af7cf6 in -[NSManagedObjectContext setUndoManager:]
#1 0x91cc3f4d in -[NSPersistentDocument setUndoManager:]
#2 0x91969ea9 in -[NSDocument undoManager]
#3 0x00002f0f in -[MyDocument init] at MyDocument.m:358
Apparently when -[NSDocument undoManager] sees that its undo manager
is nil (because I set it to nil), it says to itself, "Golly, we need
an undo manager here. So it creates one, sets it in the subclass -
[NSPersistentDocument setUndoManager:], which in turn says, "Gee, our
moc needs this too", and then invokes -[NSManagedObjectContext
setUndoManager:].
The obvious solution would be to add to the init method:
[self setHasUndoManager:nil] ;
which would probably work for NSDocument but for NSPersistentDocument,
the documentation says:
"Overridden to be a no-op ... You should not override this method.
The persistent document uses the managed object context’s undo
manager."
Overriding -hasUndoManager didn't work either. It's never invoked.
However, my third guess seems to be working. In the MyDocument
implementation I overrode...
- (NSUndoManager*)undoManager {
return nil ;
}
This seems to work. I can add employees, delete employees, open and
save documents, and there are no crashes or whineys printed to the
console. In the menu, Edit > Undo is always disabled, as expected.
In my actual application, my document subclass is in a framework, of
which my non-gui background worker and the gui app are thin wrappers.
So, I condition the code in the above methods with if(!NSApp).
Am I violating the "spirit of the docs" here, or is this solution OK?
Sincerely,
Jerry Krinock
_______________________________________________
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