views:

68

answers:

4

Hi everyone

This is really twisting my mind… I'm trying to access an NSMutableArray in an IBAction which I defined in viewDidLoad. Unfortunately I keep getting a EXC_BAD_ACCESS.

I'm new to all this so I'd really appreciate some insight in what I'm doing wrong.

Below find the corresponding code excerpts.

CounterViewController.h:

@interface CounterViewController : UIViewController{
 NSMutableArray *countHistoryArray;
}
@property(nonatomic, retain) NSMutableArray *countHistoryArray;

CounterViewController.m:

@implementation CounterViewController
@synthesize countHistoryArray;

- (void)viewDidLoad {
    [super viewDidLoad];

 //Fill array with some dummy data
 self.countHistoryArray = [[NSMutableArray alloc] init];
 NSDate *now = [[[NSDate alloc] init] autorelease];
 CurrentCount *historicCount = [[[CurrentCount alloc]
         initWithCount:[NSNumber numberWithInteger:22]
         description:@"Testcount"
         dateAndTime:now] autorelease];

 [self.countHistoryArray addObject: historicCount];

 //Do some logging - everything is working fine here!
 NSLog(@"%@", [self.countHistoryArray description]); 

}


//Later on we click on a button and want to use the array
- (IBAction)doSomeStuff {  
    //Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
 NSLog(@"%@", [self.countHistoryArray description]);
}

Thanks a lot!
Manuel


EDIT Additional code as asked for by @jamapag

CurrentCount.h

#import <Foundation/Foundation.h>


@interface CurrentCount : NSObject {
    NSNumber *counterLevel;
    NSString *description;
    NSDate *dateAndTime;
}

- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime;

@property(nonatomic, copy) NSNumber *counterLevel;
@property(nonatomic, copy) NSString *description;
@property(nonatomic, copy) NSDate *dateAndTime;

@end

CurrentCount.m

#import "CurrentCount.h"


@implementation CurrentCount
@synthesize counterLevel;
@synthesize description;
@synthesize dateAndTime;

- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime{
    self = [super init];
    if(nil != self){
        self.counterLevel = newCounterLevel;
        self.description  = newDescription;
        self.dateAndTime  = newDateAndTime;
    }
    return self;
}


-(void) dealloc{
    self.counterLevel = nil;
    self.description  = nil;
    self.dateAndTime  = nil;
    [super dealloc];
}

@end
A: 

Remove autorelease from:

currentCount *historicCount = [[[CurrentCount alloc] initWithCount:[NSNumber numberWithInteger:22] description:@"Testcount" dateAndTime:now] autorelease];

iPhoneDev
Thanks, but… I did try that before - and now again. Still the same error unfortunately.
sprain
No, the `autorelease` is fine, don't mess with that.
walkytalky
@walkytalky Thanks, that's what I was thinking, too. But I must think wrong somewhere so it was worth a try :)
sprain
A: 

Show code of initWithCount:description:dateAndTime: mehtod. I think the problem there.

jamapag
Added code to original post. Thanks!
sprain
Hmm. Looks like all is well. The only thing I can recommend is set NSZombieEnabled to YES. http://www.codza.com/how-to-debug-exc_bad_access-on-iphone
jamapag
+1  A: 

Are you sure that your code actually looks like this?

- (IBAction)doSomeStuff {  
    //Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
    NSLog(@"%@", [self.countHistoryArray description]);
}

Your question title says "NSMutableArray count causes EXC_BAD_ACCESS" - if that line of code actually says NSLog(@"%@", [self.countHistoryArray count]);, you'll almost certainly get a crash, since NSLog will attempt to treat a primitive type (the type returned by -[NSArray count]) as an object. In order to use -[NSArray count] in NSLog, use %u instead of %@:

- (IBAction)doSomeStuff {  
    // This time it should work!
    NSLog(@"Array Count = %u", [self.countHistoryArray count]);
}
Nick Forge
Ha! Very good, that works! Thank you!(I did change from count to description somewhere during time).What I do not understand though is, `NSLog(@"%@", [self.countHistoryArray description]);` is now working, too. You say it can't work, but it does. Strange stuff…
sprain
`NSLog(@"%@", [self.countHistoryArray description]);` will work - my wording may have been slightly ambiguous. In an `NSLog` style format string, you should use `%@` for any Obj-C object, and an appropriate format symbol for any C primitives (`%u` for unsigned ints, `%f` for floats etc). Also, you can just use `NSLog(@"%@", self.countHistoryArray)`, since `NSLog` will call `description` on the object for you automatically.
Nick Forge
The reason I thought that this might be the case is because it's a common mistake, which I made many times when I was learning Obj-C (and occasionally still make when I'm tired enough).
Nick Forge
Got it! Vielen Dank! :)
sprain
A: 

It looks like you are accidentally releasing countHistoryArray somewhere. Try removing all calls to it except for those two you showed. Additionally you can try enabling zombies to debug the problem.

Oh and by the way you probably don't really want a public NSMutableArray property and if you do you probably want it to be copy, not retain. Otherwise incapsulation kinda goes down the drain.

Steam Trout
Thank you! Problem one is solved.I'll look into the copy/retain thing.
sprain