Question

NSArray *array = [dictionary objectForKey:@"field"];

and

NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:@"field"]];

I see both kind of approaches very frequently in objective C code. When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one? Any idea?

Detailed explanation and useful references are moms welcome.

Was it helpful?

Solution

First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).

But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.

See the memory guide here. Specifically, look at the rules.

Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...

For example:

// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
    return [NSString stringWithFormat:@"%@ : %d", _title, _id]; 
}

// my object stuffed it away in an iVar - I need the retained version of it.  release in dealloc
- (void) prepare {
    _myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}

In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.

In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.

OTHER TIPS

You have a fundamental misunderstanding of allocations versus instance methods.

The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.

The second, however is the classic retain part of the retain-release cycle.

The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.

What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top