views:

114

answers:

3

EDIT What i am trying to achieve with the code, is to create an array of 20 unique 'Person' objects. I know now thanks to the guys below that i am going way off calling dealloc.

for (int i = 0; i < 20; i++)
{
    Person *myPerson = [[Person alloc] init];
    myPerson.name = @"Brian";
    myPerson.age = [NSNumber numberWithInteger:23];     
    [myArray addObject:myPerson];       
    [myPerson dealloc];         
}

In the process of learning Objective C, hence why this code might seem crazy to you. But I am coming from Java so my logic isn't great for Objective C yet.

I was trying to populate my array with 20 person objects. But it seems i am adding the same Object person all the time. Then deallocating it which defeats the point.

So my question is: What would be the correct way to to fill the array with 20 different person objects. The names and ages will be different in the future for each person but at the moment they all be the same while i learn.

Is the only way to do this to type a lot of code like this :

    Person *myPerson1 = [[Person alloc] init];
    myPerson.name = @"Brian";
    myPerson.age = [NSNumber numberWithInteger:23];     
    [myArray addObject:myPerson1];  
    Person *myPerson2 = [[Person alloc] init];
    myPerson.name = @"Brian";
    myPerson.age = [NSNumber numberWithInteger:23];     
    [myArray addObject:myPerson2];  
    Person *myPerson3 = [[Person alloc] init];
    myPerson.name = @"Brian";
    myPerson.age = [NSNumber numberWithInteger:23];     
    [myArray addObject:myPerson3];  

20 times? Or is there a more elegant solution?

Thanks for you advice. -Code

+6  A: 

Probably the simplest and most "obj-c" way to do this would be to create a class method on person that creates the person you want. Just like [NSString stringWithFormat], you'd return an autoreleased object so that the caller doesn't even need to release it.

Never call dealloc yourself - trust in release

- (Person*) personWithName:(NSString*)name andAge:(NSNumber*)age
{
     Person* p = [[Person alloc] init];
     p.name = name;
     p.age = age;
     [p autoRelease];
     return p;
}

Now you'll be able to add each person to the array in a single line without leaking memory

[myArray addObject:[Person personWithName:@"Brian" andAge:23]];
[myArray addObject:[Person personWithName:@"Alice" andAge:4]];
[myArray addObject:[Person personWithName:@"Bob" andAge:60]];  

Further reading: http://www.cocoadev.com/index.pl?AutoRelease

Rob Fonseca-Ensor
+7  A: 

Your for loop code is correct with the exception of deallocating myPerson at the end of the loop. You do not want to deallocate it since the object is retained by the array. Generally you do not want to invoke dealloc directly, you want to use retain/release instead. For more information about memory management check out Apple's Guide

So you are correct with the exception of dealloc being changed to release.

for (int i = 0; i < 20; i++)
{
    Person *myPerson = [[Person alloc] init];
    myPerson.name = @"Brian";
    myPerson.age = [NSNumber numberWithInteger:23];     
    [myArray addObject:myPerson];       
    [myPerson release];         
}
DHamrick
Stronger: The only time any normal Objective-C program will call `dealloc` is at the end of a class's override of `dealloc`, in which case you'll write `[super dealloc]`. Any other use is almost certainly wrong.
Chuck
But is it not true to say that I have an array holding 20 copies of the same object(20 pointers to the same object)? What i am trying to do(and not understanding how) is add 20 unique objects.
Code
@Code: No, you do not have 20 pointers to the same object. A new object is created every time you write `[[Person alloc] init]`, which you do each iteration of the loop. It might have *looked* like that's what was happening with the broken code, because each time you `dealloc`ed the object, its memory location was freed and the next object was allocated at the same address.
Chuck
What my aim to achieve is what the 2nd snippet of code does, but in a loop to create 20 unique Person Objects. As 20 copies of the same person object it not very useful. Sorry for the lack of clarity in what i am trying to achieve with the code.
Code
@Code: That is what the loop is doing. It is creating 20 unique objects.
Chuck
Thanks guys. I deeply grateful for the advice.
Code
@chuck each object might point to a different reference, but they're all called Brian
Rob Fonseca-Ensor
@Rob Fonseca-Ensor: Yes, and that's just as true with the unrolled loop he wrote as "my aim to achieve." Either his dataset contains a lot of 23-year-old Brians or the actual contents of the objects are beside the point.
Chuck
Hehe you 2 just made me lol, with your dialog :D
Code
well, brian, perhaps you'd like to clarify what you're asking ;)
Rob Fonseca-Ensor
@Code: As you see from the answer from DHamrick here, and from Rob's answer, you either have to autorelease `myPerson` or release `myPerson`. Calling `dealloc` is just plain wrong. The two correct techniques are both fine, but for your understanding of Objective-C (especially for iPhone, where Garbage-Collection is not supported) it is very important that you understand the two techniques.
harms
I think I am starting to follow what you guys suggest. When I get an urge to dealloc, I should cool my jets and instead use a called to autorelease. And let it get released when the phone see's fit.
Code
myArray = [[NSMutableArray alloc] init]; is done in a startup method of my class. In the dealloc method for the class - (void)dealloc { [super dealloc];} shouldnt i add a line of code that says [myArray release]; which will then cause all the Person objects created and the array itself to be deallocated by the phone?
Code
@Code: Yep, you should. Basically you have to think of pointers in terms of owernship. Your main object owns the array, and your array owns each `Person` therein. Unlike in the real world, however, ownership is not exclusive -- another object could also own your array, without "diluting" your ownership of it. You signal the "taking" and "relinquishing" of such ownership with the `retain` and `release` methods. When your object dies (i.e. in `dealloc`), you must make sure it relinquishes all ownerships it may hold.
harms
@harms Thanks for the advice. Much appreciated.
Code
+1  A: 

As DHamrick writes you should not dealloc the object you create, this is the same as deleting the object. It was added to the array, which also retained it. But as you in the loop creates a new object I can imagine the new object will have the same address as the previously deleted one and thus the old pointers will again point at this new object, making you believe they are all one and the same. To hunt down bugs like this I suggest you look into enabling NSZombie's.

http://iphonedevelopertips.com/debugging/tracking-down-exc_bad_access-errors-with-nszombieenabled.html

epatel