1

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!

pchap10k
  • 2,066
  • 2
  • 19
  • 30

2 Answers2

17

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];
}
Alex Rozanski
  • 37,815
  • 10
  • 68
  • 69
  • 2
    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 May 12 '09 at 13:06
  • Sorry I meant that line to be self = [super init]; but yes, that is a better approach – Alex Rozanski May 12 '09 at 13:09
  • Thank you for your help everyone. I now appreciate the difference between a class declaration and instantiating a variable! – pchap10k May 13 '09 at 05:23
  • I had `myArray = [[NSArray alloc] init];` in my `init` method. However the child class wasn't calling `init`. It was calling `initWithStyle`. So my array initialization was not happening 8-) – SundayMonday Dec 16 '11 at 01:39
  • This was my mistake as well. I assumed that having it in the header and synthesizing it initialized the object. Obviously not! – dmgig Mar 07 '12 at 20:25
3

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.

Alastair Stuart
  • 4,165
  • 3
  • 36
  • 33
  • 1
    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 May 12 '09 at 16:28
  • 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 May 13 '09 at 01:39