Chris James
Chris James

Reputation: 11721

NSDictionary losing its contents (exc bad access)

So i have a uiviewcontroller. It has a property of an NSMutableArray with a nonatomic, retain property synthesized.

In the viewDidLoad I init it with the following, and also add a button to the nav bar.

test = [NSDictionary dictionaryWithObjectsAndKeys:
        [[SearchField alloc] initWithName:@"Subject" :Text], kSubjectKey, 
        [[SearchField alloc] initWithName:@"Source publication" :Text], kSourceKey,
        [[SearchField alloc] initWithName:@"Keyword" :Text], kKeywordKey,
        [[SearchField alloc] initWithName:@"Author" :Text], kAuthorKey,
        [[SearchField alloc] initWithName:@"Color" :Bool], kColorKey,
        nil ];

NSLog([NSString stringWithFormat:@"lol %d", [test count]]);

The first log, when running through the debugger runs fine. However, I have tied the following code to the button:

-(void)search:(id)sender{

    NSLog([NSString stringWithFormat:@"lol %d", [test count]]);

When this code executes the log line crashes with exc bad access. Nothing is happening to the NSDictionary between the viewDidLoad and the button press, so why is this happening? And more importantly, how do I fix it? :)

Cheers

Edit I thought maybe it was my SearchField class was doing things, so i replaced them with simple strings, the problem still occurs.

Upvotes: 0

Views: 1544

Answers (3)

Jasarien
Jasarien

Reputation: 58478

The dictionary you're creating is autoreleased. You're using a convenience method (dictionaryWithObjectsAndKeys:) which returns a new autoreleased object.

The autoreleased object is being released (and deallocated) some time after its creation, which is why it's crashing later in the program.

You need to retain the returned dictionary, or create a new dictionary using the alloc/init method.

Either way, you need to remember to release the dictionary when you're done with it.

You should read up on the basic memory management rules and conventions for Objective-C.

Upvotes: 1

Alex Reynolds
Alex Reynolds

Reputation: 96984

  1. Make sure test is a class variable, by setting it up as a property of your view controller's header:

    @property (nonatomic, retain) NSDictionary *test;

  2. Release it in your view controller's -dealloc method:

    [test release], test = nil;

  3. Set its value as follows:

    self.test = [NSDictionary dictionaryWithObjectsAndKeys:...];

  4. Access its count property as follows:

    NSLog(@"Count: %u", test.count);

    Or:

    NSLog(@"Count: %u", [test count]);

    Note that -count returns an unsigned integer, so you should use %u to format its value.

Upvotes: 3

JosephH
JosephH

Reputation: 37505

You're directly accessing the member variable - you need to go through the accessor - ie:

self.test = [NSDictionary dictionaryWithObje ...

This will make sure your object retains the dictionary.

Upvotes: 3

Related Questions