Re: Handling Undo/Redo in KVC To-Many Accessors
Re: Handling Undo/Redo in KVC To-Many Accessors
- Subject: Re: Handling Undo/Redo in KVC To-Many Accessors
- From: Chris Giordano <email@hidden>
- Date: Mon, 10 May 2004 10:15:05 -0400
Sean,
I'm early on the learning curve here, but here are a of my thoughts:
On May 7, 2004, at 1:39 PM, Sean Todd wrote:
Hi,
I am trying to handle undo/redo in insertObject:in<key>AtIndex: and
removeObjectFrom<key>AtIndex: but I am having trouble and I haven't
found anything in the archives addressing this issue. When I try to
Undo the creation of a new object in a mutable array I sometimes get
errors such as:
*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)
at which time the undo manager is hosed.
I was able to reproduce this in the ToDos example project by modifying
the following 2 methods in MyDocument.m:
- (void)insertObject:(id)anObject inToDosAtIndex:(unsigned int)index
{
[toDos insertObject:anObject atIndex:index];
NSUndoManager* um = [self undoManager];
[[um prepareWithInvocationTarget:self]
removeObjectFromToDosAtIndex:index];
}
- (void)removeObjectFromToDosAtIndex:(unsigned int)index
{
NSUndoManager* um = [self undoManager];
id item = [self objectInToDosAtIndex:index];
[[um prepareWithInvocationTarget:self] insertObject:item
inToDosAtIndex:index];
[toDos removeObjectAtIndex:index];
}
If you create a new toDo object and then immediately try to Undo the
creation you get the error. But, if you create a new toDo object and
then deselect the item in the table before Undoingthen it works as I
would expect. Does anyone know what's going on here? Have I missed
something obvious (highly likely) or is this a bug that I need to
report? Any suggestions for a workaround?
From some testing, it appears that it's crashing because it's
attempting to do something (probably restore) the selection in the
table, but since the selected indexes now extend past the end of your
array, it's complaining.
There are two things that I could see doing to fix this. The first is
probably easiest -- assuming that it works in all of your cases. That
would be to simply remove the selection when you delete. You could do
something to attempt to restore it (i.e., scan the previously selected
indexes/objects and reselect then once you're done with your delete).
The other approach is to have your array controller (I assume you're
using an array controller to bind your model to your view here) handle
the insertion and deletion. Or, more specifically, register your undo
actions with your array controller rather than with your model.
I'll leave it to you as to how to deal with all of the specifics, but
below is some code that I have that deals with an array (transactions)
managed with an NSArrayController subclass called
registerArrayController. For me, order isn't important, which is
somewhat significant since I don't deal with the indices. It's also
the case that the ordering of my array can change between the action
and the undo of that action, so doing it by index wouldn't work. If
order is important to you, you'll need to deal with the index on
insertion, but could probably still just remove the item directly
(i.e., removeObject:) rather than by index.
chris
- (void) insertObject:(id)obj inTransactionsAtIndex:(unsigned int)index;
{
[[[self undoManager]
prepareWithInvocationTarget:registerArrayController]
removeObject:obj];
if ([[self undoManager] isUndoing])
[[self undoManager] setActionName:@"Remove Transaction"];
else
[[self undoManager] setActionName:@"Add Transaction"];
[transactions insertObject:obj atIndex:index];
}
- (void) removeObjectFromTransactionsAtIndex:(unsigned int)index;
{
id trans = [transactions objectAtIndex:index];
if (trans)
{
[[[self undoManager] prepareWithInvocationTarget:self]
insertObject:trans inTransactionsAtIndex:index];
if ([[self undoManager] isUndoing])
[[self undoManager] setActionName:@"Add Transaction"];
else
[[self undoManager] setActionName:@"Remove Transaction"];
[trans removeObserver:self];
[transactions removeObjectAtIndex:index];
}
}
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.