views:

1368

answers:

2

I am using the iPhone SDK and have an issue doing something simple. I am trying to add an NSNumber object to an NSMutableArray instance variable. I tried adding NSNumber card to NSMutableArray viewedCardsArray, however without breaking, it does not get added to the array. Here is the code.


/////////////////////////////////////////////////////
// Inside the header file Class.h
@interface MyViewController : UIViewController {
   NSMutableArray *viewedCardsArray;
   //snip ...
}
@property (nonatomic, retain) NSMutableArray *viewedCardsArray;
@end

/////////////////////////////////////////////////////
// Inside the methods file Class.m
#import "StudyViewController.h"

@implementation StudyViewController
@synthesize viewedCardsArray
  //snip ...

- (IBAction)doShowCard {
   //snip ...
   NSNumber *cardIdObject = [[NSNumber alloc] initWithInt:(int)[self.currentCard cardId]];
   [viewedCardsArray addObject: cardIdObject];
   [cardIdObject release];
}

So this code executes, and does not seem to leak (according to the Leaks performance tool). However when stepping through the code, at no point does CardIdObject appear in viewedCardsArray.

Looking through SO, I know these basic questions are pretty common to ObjC newbies (like me) so apologies in advance!

+5  A: 

Have you initialized your viewedCardsArray? If not you need to somewhere - this is usually done in the init method for your class:

- (id)init
{
    self = [super init];
    if(self) {
        viewedCardsArray = [[NSMutableArray alloc] init];
    }
    return self;
}

Then it is released in the dealloc method:

- (void)dealloc
{
    [viewedCardsArray release];
    [super dealloc];
}
Perspx
Don't forget to use the result of [super init]. It can return nil or a different object. Never assume that it returned your former self, because when it doesn't, it released it, and any further initialization you do of that now-dead object will probably cause a crash. The simplest way is if ((self = [super init])) { /*initialize here*/ } return self; (subject to your own style taste—for example, you can have the assignment before the condition if you want).
Peter Hosey
Sorry I meant that line to be self = [super init]; but yes, that is a better approach
Perspx
Thank you for your help everyone. I now appreciate the difference between a class declaration and instantiating a variable!
crunchyt
+1  A: 

Perspx has outlined one way of initializing the array. However, you can also use the class methods provided by NSArray:

self. viewedCardsArray = [NSMutableArray array];

This can go in init or elsewhere.

Note: The object will be autoreleased.

coob
The problem with that is that when you set your own properties in -init, you're sending messages (specifically, accessor messages) to a not-fully-initialized object (self). The same is true in reverse in -dealloc. This can become a problem if you implement a custom accessor that assumes that some other ivar has already been initialized and that the object in it (if any) is still valid.
Peter Hosey
If you're using synthesized properties, this is a perfectly valid way of doing things. There's Apple code which does this, for example, as well as the inverse: using self.someProperty = nil in the -dealloc method.
Jim Dovey
Thanks, this is useful to know
crunchyt