I declare my array in my *.h file:
@interface aViewController: UIViewController { NSMutableArray *anArray; // You will need to later change this many times. } @end
I alloc memory for it my *.m file:
-(void) viewDidLoad { anArray = [[NSMutableArray alloc] init]; }
I click a test-button to load my array (eventually it will need to load DIFFERNT values on each click):
anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
And I free it here:
-(void) dealloc { [anArray release]; [super dealloc]; }
Does that all look ok?
Because it crashes when I later run this code:
NSLog(@"%d", [anArray count]);
Not sure why a simple "NSLog() and count" would crash everything.
Dirk,
Let me put it this way: I have a HUGE misunderstanding of pointers, arrays, strings, and memory.
I've read everything I can find on it... but (yet) to find a simple, clear, easy-to-understand description.
Can you suggest one? (Hopefully less than 10 pages of reading.) Is there a reference that explains JUST this topic... and from a standpoint of "you have 12 years of coding experience... but NONE that ever dealt with allocating memory or pointers".)
So the variable-name is NOT the way I refer to the object? Then why have it?
I'm used to many other languages that just do this:
myString = "this" myString = "that" myInt = 5 myInt = 15
(What could be simpler.)
Looks to me like this would be the easiest way to do this. (And it seems to work. But it is truly correct?)
Don't alloc any memory for my NSMutableArray initially. Don't re-alloc any memory repeatedly. (When I change my array's values.) Don't release it repeatedly. (Before I change my array's values.) Don't release it when I exit the program. But: Always remember to use RETAIN when I initially assign (and repeatedly reassign) new values to my anArray variable.
You are not loading your array with anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil]; Instead, you are replacing it with a new instance, and worse: with an instance, whose reference is actually owned by some entity you do not control
Wow. So I could have 20 arrays... all called the same name: anArray... and they would be all different? (There's no such thing as a GLOBAL array?)
etc. In order to clear out old values, the method removeAllObject may be handy. There are also mutation methods, which may be used to add multiple values at once.
So... first I have to "remove all the objects"... and then I can call ONE method it re-add all my new values.
anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain]; instead of the alloc/init sequence.
Wow. I thought nothing could be stored in an array without alloc'ing space for it.
If you really intend to replace the entire array, you may want to consider using properties
How would I do that using properties?
What would be the correct way to do something like this:
> anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil]; > anArray = [NSMutableArray arrayWithObjects:@"four", @"five", @"six", nil];
Just like I would do:
x = 12; x = 24;
Wow. I REALLY have totally misunderstand everything about strings, arrays, and memory. I thought the "easy way" was to alloc ONCE... use the mutable array... change it as much as you want... and free it ONCE.
The problem with doing so is that this new array isn't retained,
I would think the old array would be gone... and the new array could be used. (But I guess not.)
Further, you have a memory leak because you never freed the original array.
I was thinking the old array wasn't suppose to be freed... I'm not done with it... I just wish to CHANGE it to contain my new values. (But I guess not.)
but one is to use [anArray release];
I was thinking that would cause me to release the memory I allocated... (but I guess not)... and then I'd have to re-alloc more memory. (But I guess not.)
anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain];
So I have to "retain" it... so it doesn't disappear out from under me? (Not sure why it would. Until I tell it to... in my final dealloc call.)
Another, probably more correct way to fix it would be to use the addObject: or addObjectsFromArray: NSMutableArray methods instead of constantly creating new arrays.
I only want to create ONE array... and just use it as I want to. I never want to ADD to the array. I want to set it to my new values.
You are not loading your array with
anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
Instead, you are replacing it with a new instance, and worse: with an instance, whose reference is actually owned by some entity you do not control (most likely, an NSAutoreleasePool
.) The reference you properly owned, the one created by
[[NSMutableArray alloc] init]
is lost and will be leaked.
Instead of replacing the entire array reference, mutate the one you have at your disposal already, using for example addObject:
like
[anArray addObject: @"one"]
[anArray addObject: @"two"]
etc. In order to clear out old values, the method removeAllObject
may be handy. There are also mutation methods, which may be used to add multiple values at once.
Alternatively, you can allocate the array using the construction method you already use, but be careful to retain it. In viewDidLoad
do
anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain];
instead of the alloc
/init
sequence.
If you really intend to replace the entire array, you may want to consider using properties instead of doing the reference counting manually.