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!

2 Answers 2

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];
}
Sign up to request clarification or add additional context in comments.

5 Comments

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).
Sorry I meant that line to be self = [super init]; but yes, that is a better approach
Thank you for your help everyone. I now appreciate the difference between a class declaration and instantiating a variable!
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-)
This was my mistake as well. I assumed that having it in the header and synthesizing it initialized the object. Obviously not!
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.

2 Comments

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.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.