Reputation: 6176
I've always seen that we use an intermediary object, for example, creating an array to fill in another array:
characters = [[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil];
play.characters = characters;
[characters release];
with characters
being an NSArray
in the object play
.
I saw the same thing with a @property
and its self
: we did not add the new items directly into this property, just as we don't directly fill in characters
in the example above. Is this only about "style"?
Upvotes: 0
Views: 95
Reputation: 18253
There is actually only one array in play in that little piece of code.
It is not the array that is intermediate, but the variable holding a pointer to it - in this case the variable characters.
This is what happens:
The expression
[[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil]
allocates an object and initialises it with three NSStrings (which are themselves objects, but let's leave that out for a moment). The initialisation also includes an increment of the retain count, so it is one from the get-go.
This newly created object lives at a given position in memory, say 0100H. This position is then stored in the variable characters
. In C terms we say that characters
is a pointer to the object.
Then the property @"characters"
of the object play
is set to point to the same position in memory as the local variable characters
. There are therefore now two variables (of which one is also a property) that point to the same object, or, if you prefer, to the same position in memory. If the property is of type retain, this will automatically increment the retain count of the object, so it is now 2.
With the release message in the last line, the object decrements its retain count by one, so at the end of this code snippet, the object is pointed to by the play.characters
property, and it has a retain count of one.
To be really clean, this code should probably set the local variable to nil
, to avoid confusion between variables holding pointers to the object and the retain count.
All this was meant to show that there really is only one array in play here, but two variables that point to it. So there are not as many computer resources being wasted as it might seem at a first glance.
If you wanted to do it all in a single line, you could write something like this:
play.characters = [[[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil] autorelease];
but the exact working of this is less clear as it involves one of those mysterious autoreleases, i.e., a release that is handled automatically and postponed to some later stage.
This is a long description, but I hope it sheds some light on what is going on.
Upvotes: 1
Reputation: 28806
This is not a matter of style.
play.characters
is a property, and that can "contain" an existing array or nil
, but even if it "contains" an existing array, you can't change the contents of an NSArray
, so you'll have to create a new one and assign that to the property.
Assigning to a property will, if all was declared well, cause its setter method to run (which could be created by the compiler, if you used @synthesize
, or written by you, in code) and that will take care of removing any existing array, assigning the new one and retaining it.
Upvotes: 2