Re: help needed with OO concepts when copying
Re: help needed with OO concepts when copying
- Subject: Re: help needed with OO concepts when copying
- From: Chris Giordano <email@hidden>
- Date: Tue, 11 Feb 2003 17:05:08 -0500
Denis,
Actually, you are making a copy of the array (or two when you copy the
array you send with the setBlock: message) . Unfortunately, you're not
also copying the elements of the array, so all two (or three) arrays
contain the same set of objects. That may not make things clearer.
Let me try to elaborate.
What you've got is a bunch of objects (your blocks). These objects are
put into your first array. This first array is essentially a list of
pointers to your objects. When you create your second array by just
copying the first array, what you are doing is creating another list of
pointers to your original objects. The objects in the two arrays are
actually the same objects, so changing an object via one array will
also cause references to the object via the second array to have this
change. You still only have one set of objects (blocks).
In C terms, you're doing something like the following:
int data = 10;
int *first = &data;
int *second = first;
You now have to pointers that point at the same data. Any changes to
data will be reflected in both first and second. What you want to do
is copy the contents of data and put it into a new integer. That's not
what you're doing in your code.
What you need to do is to copy the items as well as the array. You can
do this manually by creating an empty second array, iterating over the
first one and inserting copies of each object into the second one. You
can also try using some of the methods that Cocoa provides for you. I
haven't tried it myself, but the method initWithArray:copyItems: of
NSArray would probably do the trick (see
<
http://developer.apple.com/techpubs/macosx/Cocoa/Reference/Foundation/
ObjC_classic/Classes/NSArray.html#BCIFDAHF> for details).
So, in your setBlocks: method (which has a few other issues -- you're
allocating myBlocks, and then leaking that one when you use "myBlocks =
[newBlocks copy]"), you'd want to do something like the following.
- (void)setBlocks: (NSMutableArray *) newBlocks
{
if (blocks == newBlocks) return; // save yourself some work in case
they are the same
NSMutableArray * oldBlocks = blocks;
blocks = [[NSMutableArray alloc] initWithArray:newBlocks
copyItems:YES];
[oldBlocks release];
}
After this method is performed, blocks will point to a new array with
objects that are copies of those in the original array. Assuming that
your blocks are such that they will produce a different object when
sent a "copyWithZone:" message, you should have what you need.
Hope this helps.
chris
On Tuesday, February 11, 2003, at 02:55 PM, Denis Stanton wrote:
Hi
I hope someone can help me out with a gap in my understanding of object
concepts. I'm trying to make a copy of an MSMutableArray, so that I
have two arrays. I then try and modify the text contents of one of the
arrays and I see the same changes occur in the other array. This tells
me that rather than making two arrays all I am doing is making two
references to the same one. I have spent many hours trying to figure
out this copying thing, but I'm stumped. How do I make a separate copy
of an array with the same initial values as the original, but otherwise
independent of it?
In my app I have an NSMutableArray named reports.
NSMutableArray *reports;
int reportIndex;
reports = [[NSMutableArray alloc] init];
Each row of this array defines the format for a report my app will
produce. The rows are defined by the Report class.
A Report instance contains three items, a report name, report title and
an array defining the items to appear in the report. This array is
called blocks and contains instances of Block.
@interface Report : NSObject <NSCoding> {
NSString *name;
NSString *title;
NSMutableArray *blocks;
}
- (NSString *)name;
- (void)setName: (NSString *)value;
- (NSString *)title;
- (void)setTitle: (NSString *)value;
- (NSMutableArray *)blocks;
- (void)setBlocks: (NSMutableArray *)newBlocks;
@end
@implementation Report
- (void)setBlocks: (NSMutableArray *) newBlocks {
[blocks autorelease];
NSMutableArray *myBlocks = [[NSMutableArray alloc] init];
myBlocks = [newBlocks copy];
blocks = myBlocks;
}
The problem comes when I want to define a new report. The chances are
that a new report will resemble an existing one, with some changes, so
I thought the best thing to offer the user is a duplicate button which
adds another row to the reports array, copying a selected row. The new
row could then be modified. This works fine for the name and title
fields, but not for the blocks array. When I think I'm making a copy of
the blocks array I am actually just making more references to it.
- (void)tableViewSelectionDidChange: (NSNotification *)aNotification {
reportIndex = [tableView selectedRow];
}
- (IBAction)duplicateReport:(id)sender
{
Report *report = [[Report alloc] init];
[report setName: [[reports objectAtIndex: reportIndex] name]];
[report setTitle: [[reports objectAtIndex: reportIndex] title]];
[reports setBlocks : [[reports objectAtIndex: reportIndex]
blocks]];
[reports insertObject: report atIndex: reportIndex];
[tableView reloadData];
}
I thought the requirement was to set the blocks array in the new report
row to be a copy of the blocks array in the existing report row, but
this doesn;' seem to help.
Can anybody see what I'm missing here?
I tried adding a copy request, but that doesn't seem to make any
difference
[reports setBlocks : [[[reports objectAtIndex: reportIndex]
blocks]
copy]];
Thanks in advance for any advice.
Denis Stanton
_______________________________________________
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.