Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

AxoNeuron

macrumors 65816
Original poster
Apr 22, 2012
1,251
855
The Left Coast
I have always been unsure of when and how I should allocate and initialize an NSArray or NSMutableArray. For example, if I have an NSMutableArray object property, I should use lazy instantiation for it should I not?

What about NSUserDefaults? It seems to work even if I don't Alloc/Init it. Is there some place I can get this very simple information? Apple's documentation on these classes don't seem to say, I'm sure they assume you already know such basic information :)
 
Yes, you need to create an instance of the array. If not you can't add any object to it.


Code:
NSMutableArray *list;

[ list addObject:foo];
Will technicall work, but not doing what is intended as no array is created. Only a reference to an array with NULL as value.

Code:
NSMutableArray *list;
list = [ [ NSMutableArray alloc] init];
[ list addObject:foo];
Here we create a real list and can assign real entries. Note: maybe better to use the convinience methods like [NSMutableArray arrayWithCapacity:5]; which I preferr.

NSUserDefaults is doing that for you. Via its methods it delivers you an instance of an Array with the desired content.

Try this in debugger:
Code:
NSMutableArray *list;

[ list addObject:foo];      // will do nothing as no list got created

list = [ [ NSMutableArray alloc] init];
[ list addObject:foo];    // one object added to list

And watch what happen with list.
 
Last edited:
I have always been unsure of when and how I should allocate and initialize an NSArray or NSMutableArray. For example, if I have an NSMutableArray object property, I should use lazy instantiation for it should I not?

What about NSUserDefaults? It seems to work even if I don't Alloc/Init it. Is there some place I can get this very simple information? Apple's documentation on these classes don't seem to say, I'm sure they assume you already know such basic information :)

In my opinion it's preferred to use lazy instantiation when you're using an instance of the object in several places. Meaning if you declare it in the public or private interface. If you only need the mutable array locally inside a method you could declare, allocate and initialize it there.

NSUserdefaults is active over several apps. Allocation and so on is done by the OS.
 
Looks like I slightly misunstood the question before my first cup of tea ....

So I would like to add: yes, lazy init on the property and checking if not already done before sometimes/somewhere else

If (_list == Null)
{
... Do the init here
}
 
The easiest place would be in the getter method. Just do

Code:
@property (nonatomic, strong) NSMutableArray   *myMutableArray;


...

- (NSMutableArray)myMutableArray {
     if (!_myMutableArray) {
          _myMutableArray = [[NSMutableArray alloc] init];
     }

     return _myMutableArray;
}
 
Code:
NSMutableArray *list;
[ list addObject:foo];
Will technicall work, but not doing what is intended as no array is created. Only a reference to an array with NULL as value.
Actually, that code might not work. Only iVars are initialized to nil. If you do NSMutableArray *list; inside a function, it is a garbage pointer. It might be nil. But it might point to unowned memory and cause a segfault when you do [list addObject:foo] on it.

The easiest place would be in the getter method. Just do
Code:
@property (nonatomic, strong) NSMutableArray   *myMutableArray;
...
- (NSMutableArray)myMutableArray {
     if (!_myMutableArray) {
          _myMutableArray = [[NSMutableArray alloc] init];
     }

     return _myMutableArray;
}
Don't forget that that implementation is not thread-safe. If you happen to call something.myMutableArray on two threads simultaneously, you will get a race condition and leak memory.
 
Actually, that code might not work. Only iVars are initialized to nil. If you do NSMutableArray *list; inside a function, it is a garbage pointer. It might be nil. But it might point to unowned memory and cause a segfault when you do [list addObject:foo] on it.


Don't forget that that implementation is not thread-safe. If you happen to call something.myMutableArray on two threads simultaneously, you will get a race condition and leak memory.

Of course, or
1 declare in interface-end, do lazy instantiation and inside the method use [self.list addObject:foo] hence using the getter, list being myMutableArray
or
2 everything in the method
NSMutableArray *list = [[NSMutableArray alloc] init];;
[ list addObject:foo];

I wonder in the 2nd case would there be a problem if list were already allocated and instantiated globally
 
Last edited:
2 everything in the method
NSMutableArray *list = [[NSMutableArray alloc] init];;
[ list addObject:foo];

I wonder in the 2nd case would there be a problem if list were already allocated and instantiated globally

If list had items in the array, your alloc/init would remove them from the list. That's why you'll need an if statement to check if list already exists before doing an alloc/init.
 
The easiest place would be in the getter method. Just do

Code:
@property (nonatomic, strong) NSMutableArray   *myMutableArray;


...

- (NSMutableArray)myMutableArray {
     if (!_myMutableArray) {
          _myMutableArray = [[NSMutableArray alloc] init];
     }

     return _myMutableArray;
}

Doesn't the default getter already do pretty much the same thing?
 
If list had items in the array, your alloc/init would remove them from the list. That's why you'll need an if statement to check if list already exists before doing an alloc/init.

So the NSMutableArray *list = [[NSMutableArray alloc]init] will make the pointer to the array shift from for instance 36 to 752. Is this also the case with different scopes: list could be inside a method while self.list continues to exist?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.