views:

384

answers:

7

I have an NSMutableArray as a member variable for a class.

In the .h file:

@interface bleh {
NSMutableArray *list;
}

@property (readonly, assign) NSMutableArray *list;

@end

In the .m file:

@implementation bleh
@synthesize list;
-(void)init;
{
    list = [NSMutableArray arrayWithCapacity:30];
}
@end

Now, I'm not really an objective-C programmer, so maybe I'm missing some of the nuances, but when I do the following:

NSMutableString *listItem = [NSMutableString stringWithString:@"Foobar"];
[list addObject:listItem];

I'm getting strange behavior. Namely, I'm using this to keep a list of files that I eventually want to attach to an email and then open the picker. I'm getting a SIGABRT, and upon debugging, I find out that whenever I operate on list, I'm getting nothing. addObject messages don't increase the size of the NSMutableArray at all.

Am I missing something? Can someone show me a full implementation of setting up an NSMutableArray to be manipulated within a class in Objective C?

Thanks.

PS - Assume that I'm smart enough to put the manipulations of the NSMutableArray inside of a member function for the class containing the member variable.

A: 

It doesn't look as though you've actually initialized the NSMutableArray.

In the init event of the object, just say [self setList:[[NSMutableArray alloc] initWithCapacity:10]]];

(I would just say init, but I don't remember if that works. It doesn't matter what capacity you start with)

Before actually allocating the array, the variable "list" will have a value of nil.

Joe
+2  A: 

How are you actually creating your array? Is it possible that it's being autoreleased and going away? Remember, if you create it with a convenience method (like array or something) you need to retain it.

Jason Coco
I'm creating with:list = [NSMutableArray arrayWithCapacity:0];Do I need it to be:list = [[NSMutableArray arrayWithCapacity:30] retain];?
Sam
just do [[NSMutableArray alloc] init] no need to define capacity
Daniel
Yes, that's exactly what you need and that's exactly the issue. The object is getting autoreleased which is why you're getting an abort signal, the memory being referenced is bad.
Jason Coco
Thanks, I'll give that a try. Bah, the autorelease mechanism baffles me a tiny bit :P Thanks, I'll put out an acceptance when I try it out.
Sam
+1  A: 

Are you initializing your list properly? Ie do you have something like the following in your code?

list = [[NSMutableArray alloc] init];
Tom
+1  A: 

Problem ehre (assuming you initing your array properly) could be that @"Foobar" assings an NSString not an NSMutableString so its failing because if distinct types you should do

 NSMutableString *listItem = [NSMutableString stringWithString:@"Foobar"];
    [list addObject:listItem];

or

  NSString *listItem =@"FooBar";
        [list addObject:listItem];
Daniel
Hi Daniel, thanks for the suggestions. I wrote that example on the fly, you are probably right, but let's assume that this isn't the issue. Thanks for the response.
Sam
Right, so i would have to agree with everyone else about you array not being inited correctly
Daniel
+2  A: 

You're creating the array with arrayWithCapacity:, which returns an array you don't own, and you're never claiming ownership over it. Use a property accessor to retain the array:

self.list = [NSMutableArray arrayWithCapacity:30];

I would recommend reading the Cocoa memory management docs. Once you know the rules in there, it will be clear what to do in this sort of situation. They're not very hard, but they are very necessary if you're going to be programming Cocoa.

Chuck
His property declaration is (readonly, assign), so this would just fail (due to the read-only) and even if he removed that (but it may be necessary as he may not want external objects to set this property) it would still be released since he hasn't declared a retaining property.
Jason Coco
+1  A: 

Your list variable has been auto-released and de-allocated, therefore your program crashes when you try to access it.

There are two ways to create objects in Cocoa:

NSMutableArray* array1 = [[NSMutableArray alloc] initWithCapacity:10];
NSMutableArray* array2 = [NSMutableArray arrayWithCapacity:10];

array1 was created using alloc+init, therefore you own it. It will stick around until you release it.

array2 was not created using alloc+init, therefore you do not own it. You're not responsible for releasing it, but it will go away on its own. You must retain array2 if you want it to stick around.

Darren
+2  A: 

Your list property declaration is keeping you from properly retaining the NSMutableArray. By calling arrayWithCapacity you're effectively putting the array in an autorelease pool, which means it could be deallocated at any time if no object interested in keeping it around. While you are, the way you have things declared doesn't reflect that:

@property (readonly, assign) NSMutableArray *list;

The above declaration simply sets this pointer to be a copy of another pointer - it does no memory management for you. Instead it should read:

@property (readonly, retain) NSMutableArray *list;

... and you should assign the list like so:

self.list = [NSMutableArray arrayWithCapacity:64];

Because you specify the retain attribute for the property, whenever it is assigned a new value the retain message will be sent to that new value, communicating to the memory manager that you don't want this object deallocated. In order to bring this full circle, you'll need to release the object when you containing class is deallocated:

- (void)dealloc
{
    [list release];
    [super dealloc];
}
fbrereto