2

in Programming in Objective C2 book (Stephen Kochan), there was the following array:

NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:
    @"one, @"two", @"three", nil];

and another array declared as follows:

NSMutableArray *arr2;

and a shallow mutable copy takes place as follows:

arr2 = [arr1 mutableCopy];

according to textbook, arr2 now holds a new array but with object references to arr1 objects not real copies for objects in the array.

the book says, to change the first element of arr2 without affecting arr1's first element, write the following lines:

NSMutableString *mStr = [NSMutableString stringWithString:[arr2 objectAtIndex:0]];
[mStr appendString: @"ONE"];
[arr2 replaceObjectAtIndex: 0 withObject: mStr];

can anyone explain why the the first element of arr2 only affected but not the first element of arr1 too ?

1
  • Note that mStr is a whole new object. Before -replaceObjectAtIndex:withObject:, it didn’t exist in either arr1 or arr2, and the object at index 0 was in fact the same object in both arrays. You haven’t simply changed the object at index 0 (which would affect both arrays) — you’ve replaced it in array2 with an entirely new object. Commented Apr 17, 2011 at 9:39

1 Answer 1

2

You have two different Arrays. That's the answer :).

In detail:

  • arr1 and arr2 are different
  • the elements inside them are pointer to the same objects

When replacing the first object of arr2, you dont overwrite the previous object. And because both array are not the same (only the elements were), the replacement only takes place for arr2 and not arr1.

Again, more detailed:

You need to understand what an array is. They are only a list of pointers to objects. When creating an array with 3 objects, you have an array with 3 pointers to the 3 objects. When you create a copy of that array, you don't create a copy of the objects, but a copy of the 3 pointers. So your arr2 will be a different object with its own 3 pointers pointing to the 3 elements (obj1.. obj3). Now, when you do replaceObjectAtIndex:withObject you only exchange the pointer of arr2 with another one (pointing to another obj (mStr). Because both arrays (arr1 and arr2) are not the same objects (you created a copy), this will only affect arr2 (again: you only changed the pointer of arr2 - you did not change obj1 at all!!).

When you write [obj1 appendString:@"changed"] this will affect both arrays, because both are pointing to obj1.

Hope this makes it more clear for you!

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

6 Comments

added image for better understanding. just the pointer of arr2 changed from obj1 to obj4. So arr1 is not affected.
@harakiri: I think the image you provided is a little bit incorrect, because both arrays reference same objects in memory, and therefore both images of obj1 must be one image, and both images for obj2 must be one image, etc ... and yes both arrays are different but holds SAME object references, this implies that affecting one object will reflect the change to the same object in the other array and vice versa, still can't get a real reason behind this weid behaviour..
the idea was: same color = same object. but you're right.. not the best visualisation =)
@harakiri: yes ;) images make some conflict .. but still can't get the answer why :(
While your answer is correct for the most part, obj1 = @"a new string" affecting both arrays is misleading.
|

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.