Re: [Q]: Object ownership, undos, tableview, etc.
Re: [Q]: Object ownership, undos, tableview, etc.
- Subject: Re: [Q]: Object ownership, undos, tableview, etc.
- From: Brian Webster <email@hidden>
- Date: Thu, 18 Oct 2001 17:07:41 -0500
On Thursday, October 18, 2001, at 03:54 PM, cocoa-dev-
email@hidden wrote:
I have a NSMutableArray of object that I keep in my model
object. One of the operations that I would like to have
undo/redo on are insertion and removal of objects from the
array. For example, I have these methods:
- (void)insertItem: (id)item at: (int)pos;
- (void)removeItemAt: (int)pos;
- (id)itemAtIndex: (int)pos;
1. Looking at NSUndoManager, I can either use the simple undo or
invocation base method. When a object is removed from the array
(either by undoing or redoing an insertion), I would like to
preserve that object and its index on the undo/redo stack. The
natural question is that who should (or have already) retain(ed)
the object? I read that the invocation based undo does not
retain the argument object, but I'm not certain if the simple
undo method does or not. In either case, someone will have to
retain it before can be removed. What's the best way to do this?
It doesn't say explicitly one way or the other in the docs, but
I believe that NSUndoManager does retain the argument objects,
i.e. it sends a retainArguments message to the NSInvocation that
it creates. I've never retained the arguments in my undo
implementations and everything seems to work OK.
3. If I'm displaying this array of object is a NSTableView, one
item per row, and I allow the user to select multiple rows and
delete them, will all the removal be group together in one undo
action? I know that as long as I remove from the bottom up, the
order of insertion/removal will be consistent, but I want to
make sure that I don't need to treat multiple removals
differently than a series of single removals.
The way I've handled this in the past is to make a
multiple-delete into a series of single deletions and put my
undo code in the single delete. The only tricky part is when
going through your multiple deletions to make sure that you
delete the object at the correct index each time, since the
indices of each object will change as objects are removed.
Here's a code snippet from one of my apps that deals with
removing words from a list. The key to it is that the
wordIndices array (an array of NSNumbers) is sorted in ascending
order, so for each word that's removed, the index for each
successive word is decremented by 1. This is handled by
subtracting i from the index on each iteration. This will also
handle discontiguous selections.
-(void)removeWordIndices:(NSArray*)wordIndices
{
int i, index;
for(i = 0; i < [wordIndices count]; i++)
{
index = [[wordIndices objectAtIndex:i] intValue] - i;
[self removeWordAtIndex:index];
}
}
-(void)removeWordAtIndex:(int)index
{
Word *word = [[words objectAtIndex:index] retain];
[words removeObjectAtIndex:index];
[[[self undoManager] prepareWithInvocationTarget:self]
insertWord:word atIndex:index];
[word release];
}
-(int)insertWord:(Word*)word atIndex:(int)index
{
[words insertObject:word atIndex:index];
[[[self undoManager] prepareWithInvocationTarget:self]
removeWordAtIndex:index];
}
4. Is the customary method to update a NSTableView to send it a
reloadData message? Can I update just one cell (for efficiency)?
Yes, reloadData is the way to do it. There is no method for
updating a single row (yet).
--
Brian Webster
email@hidden
http://homepage.mac.com/bwebster