views:

79

answers:

2

A friend and I are creating a card game for the iPhone, and in these early days of the project, I'm developing a Deck class and a Card class to keep up with the cards. I'm wanting to test the shuffle method of the Deck class, but I am not able to show the values of the cards in the Deck class instance. The Deck class has a NSArray of Card objects that have a method called displayCard that shows the value and suit using console output(printf or NSLog). In order to show what cards are in a Deck instance all at once, I am using this, [deck makeObjectsPerformSelector:@selector(displayCard)], where deck is the NSArray in the Deck class. Inside of the Deck class, nothing is displayed on the console output. But in a test file, it works just fine. Here's the test file that creates its own NSArray:

#import <Foundation/Foundation.h>
#import "card.h"

int main (int argc, char** argv)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    Card* two = [[Card alloc] initValue:2 withSuit:'d'];
    Card* three = [[Card alloc] initValue:3 withSuit:'h'];
    Card* four = [[Card alloc] initValue:4 withSuit:'c'];
    NSArray* deck = [NSArray arrayWithObjects:two,three,four,nil];

    //Ok, what if we release the objects in the array before they're used?
    //I don't think this will work...
    [two release];
    [three release];
    [four release];
    //Ok, it works... I wonder how...

    //Hmm... how will this work?
    [deck makeObjectsPerformSelector:@selector(displayCard)];
    //Yay! It works fine!

    [pool release];

    return 0;
}

This worked beautifully, so I created an initializer around this idea, creating 52 card objects one at a time and adding them to the NSArray using deck = [deck arrayByAddingObject:newCard]. Is the real problem with how I'm using makeObjectsPerformSelector or something before/after it?

+1  A: 

When you add the objects to the array, it increments the retainCount by one. That is why releasing it doesn't dealloc the object. The array is created in the autoreleased state. When you release the pool, it releases the array and all the objects. You must understand that release is not equal to free. It just decrements the retainCount. Only when retainCount goes to zero is it freed. so outside of your function, you must somehow retain the object.

lucius
I used retainCount and it is 2 right after the Card objects are added to the array and 1 after I call release on the pointer that creates new cards. I still don't understand why its not showing the value of the cards from the array.
QuakAttak
What if you use this code to display cards:for (Card *card in deck) {[card displayCard];}Don't use makeObjectsPerformSelector: if you don't have to. It's not as clean as sending the message directly to the object instances.
lucius
I've tried that too, and no luck. The method isn't receiving the message. Maybe I'll use a C-style array.
QuakAttak
When you're calling [card displayCard], is it in another function outside of main()? If so you need to retain the array. Making it a C-style array isn't the answer.
lucius
It didn't matter after all, I was returning nil in my initializer.
QuakAttak
A: 

If you want to see the retain count live and in action, call something like:

int main (int argc, char** argv)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    Card* two = [[Card alloc] initValue:2 withSuit:'d'];
    NSLog(@"Current retain count for the '2' Card: %ud", [two retainCount]);

    Card* three = [[Card alloc] initValue:3 withSuit:'h'];
    Card* four = [[Card alloc] initValue:4 withSuit:'c'];
    NSArray* deck = [NSArray arrayWithObjects:two,three,four,nil];

    NSLog(@"Current retain count for the '2' Card after array retains it: %ud", [two retainCount]);

    [two release];
    [three release];
    [four release];

    NSLog(@"Current retain count for the '2' Card after releasing instance: %ud", [two retainCount]);

    [deck makeObjectsPerformSelector:@selector(displayCard)];

    [deck release];
    NSLog(@"Current retain count for the '2' Card after releasing instances within 'deck' array: %ud", [two retainCount]);

    [pool release];

    return 0;
}
Alex Reynolds
Thanks, this did help, and there is a retain count of one for objects in the NSArray of the class.
QuakAttak