I still did not get the full picture by reading all the answers above. The layman exercise I did below, finally helped me understand what is happening. Just putting it out there in case it helps other beginners.
Suppose you have following
@interface Class X
-(void) methodX:(NSMutableArray *)array;
@end
In some other part of the code you have the following sequence
ClassX *objectX = [[ClassX alloc] init];
NSMutableArray *arrayXX = [@[@(1), @(2)] mutableCopy];
//What is stored in arrayXX is the address in the heap at which the NSMutableArray object starts, lets call this address ZZZ
//array starting at address ZZZ in the heap now contains NSNUmbers @1,@2
[objectX methodX:array]
When you invoke [objectX methodX:array]
, what is being received by the method is a copy of array
. Since array contains an address (i.e is a pointer), the copy is special in that what is received is another variable with address ZZZ in it.
So, if methodX does [array removeObjectAtIndex:0]
, then the object starting at address ZZZ gets affected (now only contains one NSNUmber @(2)). So, when the method returns, the original array also gets affected.
Suppose instead methodX does array = [@[@(2)] mutableCopy];
then original array does not get affected. This is because you did not go into address ZZZ and change something. Instead you overwrote the ZZZ in the copy received by the method to a different address YYY. YYY address is the start of a NSMUtableArray object with one element NSNUmber @(2). The original ZZZ address still contains a NSMUtableArray with two elements. @(1) and @(2). So, when method returns, the original array is unaffected.