The right way to declare, assign, load and deallocate NSMutableArray

I declare my array in a * .h file:

  @interface aViewController: UIViewController
 {
    NSMutableArray * anArray;  // You will need to later change this many times.
 }
 @end

I allocate my * .m file memory for it:

  - (void) viewDidLoad
 {
    anArray = [[NSMutableArray alloc] init];
 }

I press the test button to load my array (in the end, it will need to load the DIFFERNT values ​​each time it is clicked):

  anArray = [NSMutableArray arrayWithObjects: @ "one", @ "two", @ "three", nil];

And I release him here:

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

Does everything look normal?

Since it crashes when I run this code later:

  NSLog (@ "% d", [anArray count]);

Not sure why the simple "NSLog () and counter" crash everything.


Dirk

Let me say this: I have a HUGE misunderstanding of pointers, arrays, strings, and memory.

I read everything I can find on it ... but (for now) to find a simple, understandable, and understandable description.

Can you offer it? (We hope there are less than 10 pages of reading.) Is there a link that explains JUST to this topic ... and in terms of “you have 12 years of coding experience ... but NONE that has ever dealt with memory or pointers” .)

So, is the variable name NOT the way I refer to the object? Then why?

I am used to many other languages ​​that just do this:

  myString = "this"
 myString = "that"

 myInt = 5
 myInt = 15

(Which could be simpler.)


Seems like this would be the easiest way to do this. (And it works, but is it really right?)

  Don't allocate any memory for my NSMutableArray initially.
 Don't re-alloc any memory repeatedly.  (When I change my array values.)
 Don't release it repeatedly.  (Before I change my array 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 do not load your array anArray = [NSMutableArray arrayWithObjects: @ "one", @ "two", @ "three", nil]; Instead, you replace it with a new instance and worse: with an instance whose link actually belongs to some organization that you do not manage.

Wow. So, I could have 20 arrays ... everyone called the same name: anArray ... and everything would be different? (There is no such thing as a GLOBAL array?)

etc .. To clear the old values, the removeAllObject method may be useful. There are also mutation methods that can be used to add multiple values ​​at once.

So ... first I need to “delete all objects” ... and then I can call the ONE method to add all my new values ​​again.

anArray = [[NSMutableArray arrayWithObjects: @ "one", @ "two", @ "three", zero] save]; instead of the alloc / init sequence.

Wow. I thought that nothing could be stored in the array without allocating space for it.

If you are really going to replace the entire array, you can consider using the properties

How do I do this 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];

As I:

  x = 12;
 x is 24;

Wow. I REALLY misunderstand everything about strings, arrays, and memory. I thought the “easy way” is to use ONCE ... use a mutable array ... change it as much as you want ... and free it up ONCE.

The problem with this is that this new array is not saved,

I would think that the old array will disappear ... and you can use the new array. (But I think not.)

In addition, you have a memory leak because you never freed the original array.

I thought the old array should not have been freed ... I did not do this ... I just want to CHANGE it so that it contains my new values. (But I think not.)

but you need to use [anArray release];

I thought it would make me free the memory I allocated ... (but I think not) ... and then I would have to reallocate more memory. (But I think not.)

anArray = [[NSMutableArray arrayWithObjects: @ "one", @ "two", @ "three", zero] save];

So I have to "save" this ... so that it does not disappear from under me? (I don’t know why this will happen. Until I talk about it ... in my final call to dealloc.)

Another probably more correct way to fix this would be to use addObject: or addObjectsFromArray: NSMutableArray methods instead of constantly creating new arrays.

I want to create only one array ... and just use it the way I want. I never want to add ADD to an array. I want to set it to my new values.

+6
objective-c iphone nsmutablearray dealloc
source share
3 answers

You do not load your array

anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil]; 

Instead, you replace it with a new instance and, even worse: with an instance whose link actually belongs to some organization that you do not control (most likely NSAutoreleasePool .) The link that you correctly owned is the one created

 [[NSMutableArray alloc] init] 

will be lost and will leak out.

Instead of replacing the entire array reference, change the one you already have at your disposal using, for example, addObject: for example

 [anArray addObject: @"one"] [anArray addObject: @"two"] 

etc .. To clear the old values, the removeAllObject method may be useful. There are also mutation methods that can be used to add multiple values ​​at once.

Alternatively, you can allocate an array using the build method that you already use, but be careful to save it. In viewDidLoad do

 anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain]; 

instead of the alloc / init sequence.

If you are really going to replace the entire array, you might want to use properties instead of manually counting links.

+11
source share

Problem: anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil]; This replaces the array you originally created. The problem with this is that this new array is not saved, so you lose it as soon as the method returns. In addition, you have a memory leak because you never freed the original array.

There are several ways to fix this, but use [anArray release]; anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain]; instead [anArray release]; anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain]; [anArray release]; anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain]; .

Another probably more correct way to fix this would be to use the addObject: or addObjectsFromArray: NSMutableArray instead of constantly creating new arrays.

+4
source share

Remember this simple memory rule: only free those objects . You only have objects when you create them using:

  • init (this method creates a new object with a save value of 1)
  • new (this method is similar to using alloc and init)
  • copy (this method creates a new object with a hold value of 1 and the contents of the method receiver)
  • retain (this method increases the number of deductions from 1)

The dealloc system automatically transfers objects while maintaining a null value. You must release every object that you have after you finish with it. If you release too soon, you will get a dangerous situation. If you do not release your object when you are done with it, you will get a leak.

A pointer is a special object that refers to some object in memory. This is basically a memory address (and some other data). If you want to use an object, you must alloc use memory for it, and then init ialize. You assign (with the = sign) a pointer.

 string = [[NSString alloc] init]; 

string now has a unit hold counter. But since NSString is an immutable object, it cannot be changed after initialization. One way to assign a string value is to execute it upon initialization.

 string = [[NSString alloc] initWithString: @"Hello, World!"]; 

If you need to change string regularly, you can use another class that is changed: NSMutableString . Nevertheless, the only way to change them is through a message.

 string = [[NSMutableString alloc] initWithString: @"Initial string"]; [string setString: @"Modified string"]; 

Just note that the following code is incorrect and causes a memory leak.

 string = [[NSMutableString alloc] initWithString: @"Initial string"]; string = @"Modified string"; 

In the first line, string assigned to the newly created object. In the second, string is assigned to another string. You lose the link to the newly created object and get a leak: you cannot release the object to which you have no link.

You do not have a problem when you do this using integers ( int type), because it is a "native" object. Objective-C Runtime associates these data types directly with its value, and not with a pointer.

 int1 = 4; int1 = 5; 

Note 1. Remember to always indicate at runtime what type of pointer. If you want to use string , you must define it first in your header (if it is publicly available) or in the implementation (if you want it to be hidden from other methods). Then you can freely use this name.

 NSString *string; 

A star tells runtime this is a pointer. There is no pointer for native types, so you get this.

 int int1; 

Note 2. Arrays (and dictionaries, etc.) behave like NSString , since they have both immutable and mutable options.

Note 3 .. Most classes have special methods that isolate, initialize, and automatically check everything at once.

 NSArray *myArray = [NSArray arrayWithObjects: @"Butter", @"Milk", @"Honey", nil]; 

An autorealized object does not need manual release , since the system will release for you after a while. This is very convenient in situations where you need an object only for the duration of the method or between methods, and not as a constant part of the object. When you autorelease some object in the main thread (in a GUI application), it will release d when the event loop completes the current loop (it ends when any event is processed). Learn more about Autorelease pools in Apple docs.

I hope I will help everyone who does not understand what pointers you have. I had problems for several months until I experimented. :-)

+3
source share

All Articles