On Nov 13, 2010, at 8:57 AM, William Squires wrote:
> Let's say I have some sample code that looks like:
>
> -(NSMutableSet *)allOddNumbersExcept5Set
> {
> NSMutableSet *results = [[NSMutableSet alloc] initWithCapacity:1];
>
> for (int i=1; i<=10; i+=2)
> {
> if (i != 5)
> {
> NSString *testNumber = [NSString stringWithFormat:"%d", i];
> // testNumber should now be an autoreleased NSString
> [results addObject:testNumber];
> }
> }
> return results;
> }
You should use NSNumbers to represent numbers as objects.
You are leaking the set. By the naming conventions, a caller of
-allOddNumbersExcept5Set does not receive an ownership responsibility. That
leaves this method with the responsibility of discharging the ownership
responsibility by releasing the set. You'd do that by sending it -autorelease,
since you want it to live long enough to reach the caller.
> 1) Do mutable containers (NSMutableArray, NSMutableDictionary, NSMutableSet)
> always send the 'retain' message to objects added with the 'addObject:'
> message?
Yes, but you shouldn't care. What you care about is whether your code handles
its responsibilities properly. The collection classes are in charge of
handling their responsibilities properly, and you should just assume that they
do.
It is documented that they extend the life of the contained objects for as long
as they are contained.
(And this is irrespective of their mutability.)
> 2) When you retrieve the results from the collection, does the object
> reference you get back have the same retain count as the one in the
> container? (i.e. if I add an object to an NSMutableArray (held in an
> @property) in one method, and retrieve it in another, will I get a retain
> count of 1 or 2?)
You _really_ don't care about retain counts. Don't pay any attention to them.
They will only mislead and confuse you.
Also, this juxtaposition of "the object reference you get back" vs. "the one in
the container" is very confused. Object references don't have retain counts.
Objects have retain counts. You receive a pointer to the object that is in the
container. Since the object you receive a pointer to and the object in the
container are one and the same, they have the same retain count.
> 3) Will the above code autorelease the 'testNumber' the second (and third,
> and fourth...) times through the loop when it gets another autoreleased
> NSString, or will it just re-use the existing one?
Each time through the loop, you are asking for a different string. Whether
that string is autoreleased or not is an open question (it might in fact be a
singleton that lives for the life of the process). What is definite is that
you do not receive an ownership responsibility and so should not release it
(unless you acquire an ownership responsibility by retaining it). You can know
this by the memory management rules and the naming conventions.
> 4) Would I be better off with:
>
> -(NSMutableSet *)allOddNumbersExcept5Set
> {
> NSMutableSet *results = [[NSMutableSet alloc] initWithCapacity:1];
>
> for (int i=1; i<=10; i+=2)
> {
> if (i != 5)
> {
> NSString *testNumber = [[NSString alloc] initWithFormat:@"%d", i];
> [results addObject:testNumber];
> [testNumber release];
> }
> }
> return results;
> }
>
> instead?
In this case, you do receive an ownership responsibility for the string
(because you called +alloc), and you correctly discharge that responsibility by
releasing it. Both this and the previous code were correctly handling the
memory management of the string.
This latter technique keeps the object out of the autorelease pool and so is
slightly more efficient. The efficiency gain is small enough that it doesn't
matter when targeting Mac OS X, but Apple does recommend this approach in the
more memory constrained environment of iOS apps.
The former technique is simpler (which counts for a lot), more convenient, and
less prone to errors. (For example, if you come back to a piece of code some
time later and add in an early return path, it's easy to forget that you need
to release the string.)
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]