Greetings,

I am using bindings in a (document-based) project in probably the simplest way 
one can imagine:

-My model contains an NSMutableArray
-An NSArrayController has its content bound to said NSMutableArray and is 
configured to prepare content (which takes the form of another custom model 
object)
-Said NSMutableArray is mutated only through the safe NSArrayController methods 
(-add:, -remove:, etc.)

Everything works just fine, including undo and redo, which I manage by adding 
appropriate -prepareWithInvocationTarget: calls in the model's 
-insertObject:in[PropertyName]AtIndex: and 
-removeObjectFrom[PropertyName]AtIndex: methods.

Now, I want to give the undo actions nice names.  To maintain a good MVC 
pattern I created wrapper action methods in my controller class (not the 
NSArrayController, but a custom NSViewController subclass that manages a 
variety of behaviors) such as:

- (void)addRecord:(id)sender
{
    if (! [[self undoManager] isUndoing]) {
        [[self undoManager] setActionName:NSLocalizedString(@"Add Record", 
nil)];
    }
    [[self arrayController] add:sender];
}

- (void)removeRecord:(id)sender
{
    if (! [[self undoManager] isUndoing]) {
        [[self undoManager] setActionName:NSLocalizedString(@"Remove Record", 
nil)];
    }
    [[self arrayController] remove:sender];
}

and have my buttons, menu items, etc., call these wrapper methods.

Here's the strange part: the action name appears to only have an effect in the 
*removal* case, never in the *addition* case.

To be clear: everything else works fine.  If I perform an action triggering 
-addRecord:, the record *is* added and a functional undo action *is* 
registered, just with no action name.  But this only happens in the addition 
case - in the removal case, everything works *including the action name*.

(If I move the -setActionName: into the model layer (-inserObject:…) the action 
name also works.)

For debugging, I have verified that the expected code is called in the 
controller layer, and that the undo manager is both non-nil and is the same 
undo manager instance as used in the model layer.  Indeed, I can even see that 
the action name has been purportedly set when stepping through the code:

(lldb) po [[self undoManager] undoActionName]
(id) $1 = 0x00000001045f1520 Add Record

But this never appears in the UI.  I also set a global breakpoint on 
[NSUndoManager setActionName:] and can see that it's only getting called once, 
inside my -addRecord: method.  So it doesn't seem to be getting clobbered later 
on.

I have even been able to reproduce this behavior in a minimal test project 
(mashing together the model and controller layers), which you can download from:

https://dl.dropbox.com/u/5847625/BindingsUndoTest.zip

So my questions are severalfold:

1) Has anyone else seen this and can explain what's going on?  Have I missed 
something?

2) Can anyone suggest a workaround, preferably short of moving -setActionName: 
into the model?

3) Is there perhaps a more appropriate way for me to handle undo/redo in this 
context?

This is on OS X, 10.7.4, FYI.  I am targeting Lion.

Thanks,
Conrad Shultz
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to