views:

37

answers:

2

Hey, I am new to Objective-C 2.0 and Xcode, so forgive me if I am missing something elementary here. Anyways, I am trying to make my own UIViewController class called GameView to display a new view. To work the game I need to keep track of an NSArray that I want to load from a plist file. I have made a method 'loadGame' which I want to load the correct NSArray into an instance variable. However it appears that after the method executes the instance variable loses track of the array. Its easier if I just show you the code....

    @interface GameView : UIViewController {
        IBOutlet UIView *view 
        IBOutlet UILabel *label;
        NSArray *currentGame;
    }

    -(IBOutlet)next;
    -(void)loadDefault;
...
@implementation GameView
- (IBOutlet)next{
   int numElements = [currentGame count];
   int r = rand() % numElements;
   NSString *myString = [currentGame objectAtIndex:(NSUInteger)r];
   [label setText: myString];
}
- (void)loadDefault {
    NSDictionary *games;
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSString *finalPath = [path stringByAppendingPathComponent:@"Games.plist"];
    games = [NSDictionary dictionaryWithContentsOfFile:finalPath];
    currentGame = [games objectForKey:@"Default"];
}

when loadDefault gets called, everything runs perfectly, but when I try to use the currentGame NSArray later in the method call to next, currentGame appears to be nil. I am also aware of the memory management issues with this code. Any help would be appreciated with this problem.

A: 

-objectForKey: doesn't return an object you own, you need to take ownership explicitly by retaining:

currentGame = [[games objectForKey:@"Default"] retain];

Or by using declared properties:

@interface GameView ()
@property (readwrite, retain) NSArray *currentGame;
@end

@implementation GameView
@synthesize currentGame;
// ...
- (void)loadDefault {
    // ...
    self.currentGame = [games objectForKey:@"Default"];
Georg Fritzsche
@Georg, how would it get set to `nil` though? Unless the dictionary doesn't actually contain that object maybe?
Carl Norum
@Carl: Good point, i overread the `nil` part. Chuck seems to have that covered though.
Georg Fritzsche
Brilliant! this appears to be exactly the problem. For future, what would you call a method such as <code> -objectForKey </code> which needs to be retained in order for you to take ownership? Thanks so much for your help Georg.
TaoStoner
@Carl I misspoke when I said it got set to nil. Sorry about that.
TaoStoner
@TaoStoner: You would call it a normal method. See the memory management guidelines: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
Chuck
@Tao: As Chuck said, those aren't specially named, its the other way around. The guidelines say that you need to retain objects you don't own and that you own objects you create: *You “create” an object using a method whose name begins with “alloc” or “new” or contains “copy”*
Georg Fritzsche
+2  A: 

I would be surprised if that code worked. Is Games.plist really at the top level of your bundle? It's not in your bundle's resources folder or in Documents or Application Support? I bet if you debug the method, you'll see that you're not correctly locating it.

Chuck
It appears it does work even though Games.plist is ,in fact, in my resources folder. Thanks for the suggestion though.
TaoStoner