Reputation: 4025
I've been reading some tutorials on raywenderlich.com, and came across this block of code...
_players = [NSMutableArray arrayWithCapacity:20];
Player *player = [[Player alloc] init];
player.name = @"Bill Evans";
player.game = @"Tic-Tac-Toe";
player.rating = 4;
[_players addObject:player];
player = [[Player alloc] init];
player.name = @"Oscar Peterson";
player.game = @"Spin the Bottle";
player.rating = 5;
[_players addObject:player];
player = [[Player alloc] init];
player.name = @"Dave Brubeck";
player.game = @"Texas Hold’em Poker";
player.rating = 2;
[_players addObject:player];
Even if the project is using ARC, isn't this bad code? Re-allocating and initialing the variable? Shouldn't it be allocated once and then reference a method within the class that prepares the variable for reuse by wiping the existing data?
Upvotes: 0
Views: 442
Reputation: 131418
Danh's answer is quite good.
To build on it, think of a local variable like "player" as a parking space. It can contain nothing (nil), or a car.
You can park a car in the space, do some work on the car, and then move the car somewhere else. Then you can drive a different car into the space, do some work on that car, and then drive it somewhere else.
The local variable player is a pointer, to an object of type Player. It starts out as nil.
When you execute the code player = [[Player alloc] init];
, the system allocates memory for a new Player object, initializes it, and saves the address of that object in the player
variable. The code then configures the newly-created Player object, then saves it to a mutable array. The array holds a strong reference to the new object.
Now, when you execute the statement player = [[Player alloc] init];
again, the system creates a completely new Player object, initializes it, and saves a pointer to that NEW Player object in the player
local variable. The old value that was in player
is overwritten, but that's ok, because the previous Player object has been saved to the _players array.
Upvotes: 0
Reputation: 37581
You are thinking that when you call NSMutableArray:addObject it creates a new object that is a copy of Player and places that new object into the array?
If it did then your comment: ".. allocated once and then reference a method within the class that prepares the variable for reuse by wiping the existing data" would work.
But addObject doesn't do that, it adds a reference to Player object to the array and increments the retain count. So if you did what you said the result would be an array that contains multiple references to the same object. And if you iterated through the array and printed the values they would all come out identical. The reason is that the array would contain multiple references to the same object, when what you want is unique references to different objects.
When people take about the object being added to the array (and even the Apple documentation makes this mistake) that is not literally correct. It is not the object itself that is added to the array but a reference to it. That's a very very important difference and the Apple documentation should be scolded for being so misleading, as must everybody who uses sloppy and imprecise terminology when talking about "adding" an object to the array.
If you come from a C/C++ or similar background think of NSMutableArray as being an array of pointers not an array of objects.
Upvotes: 1
Reputation: 62676
It's okay. player
is just a memory location where pointers to Player
objects are kept. It can point to many, many Player
's, one at a time.
Some referee might throw the "cuteness" flag, saying that a variable should be used for only one semantic purpose in any given scope. I'd argue in response that the purpose of the player
variable is to hold new Player
's while they get configured, before they are more permanently stored. It's the same argument that let's us say
for (int i=0; i<MAX; ++i)
without objecting that i
wrongly assumes many values while it's in scope. That's not a problem with i
, that's it's purpose.
Upvotes: 2