0

So I have found an issue with addObject where instead of appending a value to the end of an array, its just putting in the memory location of my object that I am adding(which i am re-using over and over). The end result is all the values in the array end up being the exact same, which is whatever the last entry was. Obviously, I don't want this.

How can I add a unique object to the array? This is my code to add the object...

     [listArray addObject:customer];

listArray is an MSMutable array. Customer is a class with 4 values.

I found this same issue here addObject creates a same value in all array

but that solution gives me an error of 'Thread 1: Program received signal: "SIGABRT".

I create the customer object using the code..

      else if ([elementName isEqualToString:@"CustomerListResponse"]) {
         NSLog(@"customer element found – create a new instance of Customer class...");
         customer = [[CustomerListData alloc] init];
      }

Thanks.

5
  • Please include more of the code surrounding your addObject: statement. How are you "re-using" the variable? Commented Jan 3, 2012 at 15:19
  • don't know what else I can add that is related. only have that 1 line in my method. I am parsing an XML of multiple "customer" values. I am parsing data into the class then attempting to insert the class into the array. Then, parsing the next customer value in the XML overwriting all the old customer values in the same class, then trying to store the NEW customer into the array. The problem is addObject is just storing the memory destination of my customer class over and over, rather than actually storing a new class. its just an efficiency thing I understand, but I need to get around it. Commented Jan 3, 2012 at 15:24
  • I pretty much used this tutorial for parsing verbatim if it helps... wiki.cs.unh.edu/wiki/index.php/… Commented Jan 3, 2012 at 15:25
  • You didn't use it that verbatim, that tutorial creates a new object each time, and releases it after adding to the array - you aren't doing that and that is your problem. The relevant code you need to add to your question is the code where you create the customer object. Commented Jan 3, 2012 at 15:39
  • I posted the code where I am creating the customer object. I think the issue may be WHEN in the XML i am creating the new customer class. I'm doing it at the start of processing all the customers, rather than when the XML hits an individual customer. Let me try that. Commented Jan 3, 2012 at 15:47

3 Answers 3

5

You first should make your customer object implement the NSCopying protocol. Then, you can do the following:

[listArray addObject:[[customer copy] autorelease]];

This will ensure that a new object is added to the array instead of just a pointer to the existing object that you are constantly reusing.

Note that you have to autorelease this copy as the copy method returns a new object with a retain count of 1.

Sign up to request clarification or add additional context in comments.

9 Comments

This might help a bit, but it does not get to the root of the problem.
Just an FYI autorelease throws an error with new xcode. According to them, they apparently they take care of it for you now
@JeremyP This answer indeed addresses the root of the problem. He says he reuses the same customer object over and over (the same pointer to the same block of memory). By adding the same object to the array over and over again he eventually ends up with an array of length N containing many pointers to the exact same object. Copying the object before adding it will fix his issue and is a perfectly acceptable way of doing so.
@JesseDurham This is true if you are using ARC. If you are using ARC you should probably specify that in your question. Not everyone is using it, yet. If you are using ARC you can safely add the copy without autoreleasing it.
Both of you are technically right, it just depends how I want to fix it I suppose.. but Sebastian is more directly answering the original question. Jeremy provided an alternate solution.
|
2

I'm guessing a bit here because you haven't given us enough code.

If you are doing this:

Customer customer = [[Customer alloc] init];
[customer setProperty1: @"foo1"];
[customer setProperty2: @"foo2"];
[customer setProperty3: @"foo3"];
[customer setProperty4: @"foo4"];
[listArray addObject: customer];

[customer setProperty1: @"bar1"];
[customer setProperty2: @"bar2"];
[customer setProperty3: @"bar3"];
[customer setProperty4: @"bar4"];
[listArray addObject: customer];

[customer release];

you will get the symptoms you describe. customer is pointing to the same object the second time. You have just changed its properties and the mutable array will now contain the same object in two slots (with the second set of values).

If you do this

Customer customer = [[Customer alloc] init];
[customer setProperty1: @"foo1"];
[customer setProperty2: @"foo2"];
[customer setProperty3: @"foo3"];
[customer setProperty4: @"foo4"];
[listArray addObject: customer];
[customer release];

customer = [[Customer alloc] init];
[customer setProperty1: @"bar1"];
[customer setProperty2: @"bar2"];
[customer setProperty3: @"bar3"];
[customer setProperty4: @"bar4"];
[listArray addObject: customer];
[customer release];

I guarantee you will be getting two different objects with the properties you require in the array. If you think you are doing this, you are wrong. Post the code and we'll tell you where the mistake is.

Comments

1

If you are using ARC then try:

CustomerListData *newcustomer = [[CustomerListData alloc] init];
newcustomer = [customer copy];
[listArray addObject:newcustomer];

2 Comments

Does this also works with custom init? I am getting the following error: NSInvalidArgumentException', reason: '-[Timesheet copyWithZone:]: unrecognized selector sent to instance 0xc7794d0'
I can't see how a custom init would affect this. Basically I'm suggesting creating a new object in a new memory space (using copy) rather than just adding a pointer to a memory space which may change (in the OP scenario was changing). Even if you use a custom init in the new object it should still be being alloc'd so should be fine. Make sure you are calling super in your custom init though if appropriate: "self = [super init];"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.