correct way to allocate the NSMutableArray - objective-c

I wanted to know which is the right way to allocate an NSMutableArray.
NSMutableArray *a;
Where a is a class level variable.
First method is:
self.a = [NSMutableArray alloc] init];
Second method is:
a = [NSMutableArray alloc] init];
Which method is better? Can anyone please help me out in this?

If a is a class variable, then correct way to allocate NSMutableArray will be creating a temporary array and assigning it to class variable, followed by releasing the temporary variable.
You can do this way:
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.a = temp;
[temp release];

It depends on the property type. (Though it's in most cases a retain)
You should either use a temp value or create it in one string and send an autorelease message:
self.a = [[NSMutableArray alloc] init] autorelease];
You must send an autorelease becuase a property increases retain count by one. This is the same as doing:
[self setA:array];//where array - is newly created array
Where:
- (void)setA:(NSMutableArray *)array {
if (array != a) {
[a release];
a = [array retain];//here you increased a retain count by 1
}
}
You can also use an autorelease method of creation:
self.a = [NSMutableArray array];

There are several ways. But below way is good enough per me whether you are working with ARC/Non-ARC. Just make sure you have created property.
self.a = [NSMutableArray array];//It will return autorelease object.

The difference between the methods:
1) When you use self.a ,
You use the setter & getter methods created in the #synthesize.
2) When you use just a,
You bypass the accessor methods and directly modify the instance variable. (a in here).
There are two ways to look at it.
Many programmers say that you should never call the accessors from within the implementation of the object as this adds unnecessary overhead.
Some others say that you should always use the accessors, and never access the instance variable directly.
It is generally safe to use an object directly, if you are reading its value only. If you are modifying the object, you should use the accessors in order to make sure that any other objects observing that property are properly notified.

The latest objective C syntax allows you to create mutable and non-mutable arrays very quickly.
The following two examples demonstrate this:
NSArray *objectsToAdd = [#"Ted", #"Ned" , #"Sed"];
NSMutableArray *objectsToAdd = [ #[#"Ted", #"Ned" , #"Sed"] mutableCopy ];

NSMutableArray *a = [[NSMutableArray alloc] init];

Related

May I declare the *shape outside the for loop?

NSMutableArray *shapes = [[NSMutableArray alloc] init];
for (NSDictionary *object in array) {
NSString *type = [object objectForKey:#"Type"];
ShapeFactory *shape = [[[ShapeFactory alloc] init] shapeWithType:type dictionary:object];
[shapes addObject:shape];
}
self.shapes = shapes;
I want to know if i can declare the variable *shape outside the loop and still work
Shapes should be declared outside the loop.
Shape is declared inside the loop, since you want to iterate every object.
So what you did is fine.
First of: Yes, as Roee84 said, this is valid syntax and you can do that. However, the fact that you have (deducing from the method name) a factory class pattern here and the type of the created shape seems to be defined by a special argument, I wonder why you're using ShapeFactory. Why not simply use id?
The array won't care about the object and it's probably better to not pretend the objects are of the same type as the factory class object.
That being said, your code is correct. Of course, you can also declare shape (the * is usually considered part of the type, btw) outside of the loop. You don't even need to declare a local mutable array (assuming your property is also a mutable array). I'll use id in this example just to illustrate what I said above:
self.shapes = [[NSMutableArray alloc] init];
id shape; // only declaration! note no * as id is basically NSObject *
for (NSDictionary *object in array) {
NSString *type = [object objectForKey:#"Type"];
shape = [[[ShapeFactory alloc] init] shapeWithType:type dictionary:object];
[self.shapes addObject:shape];
}
If your property is not a mutable array, you can't do self.shapes = [[NSMutableArray alloc] init], etc., of course, but then I'd suggest being completely safe with the last line and write self.shapes = [NSArray arrayWithArray:shapes]. This may seem a bit paranoid, but that way you're not just casting the mutable object to an immutable one, you actually have an immutable one (I'm writing libraries often and sometimes I have to expect users trying to be... frisky with stuff... ^^). Then it can't be mutated behind your back.

Cannot add items to an NSMutableArray ivar

My goal is to add a string to array, and I do that in a method which I call.
In this method, I get a null value in the array, and don't know why. I have this at the start of my class:
NSMutableArray *listOfEvents;
and a method which I call on each event:
-(void)EventList
{
[listOfEvents addObject:#"ran"];
NSLog(#"%#", listOfEvents);
}
I get (null) in the log.
If I put the array definition NSMutableArray *listOfEvents; in the function body, I get the string value #"ran", each time, so the array always has only one value, instead of having many strings named #"ran".
What's wrong with this? It seems that I can't understand something about arrays, even though I have read the documents a number of times.
I'm assuming you haven't initialized listOfEvents.
Make sure you do listOfEvents = [[NSMutableArray alloc] init]; in your class's init method. Also make sure you release it in your class's dealloc method.
If you're getting nil in your log message, you need to make sure listOfEvents is non-nil before adding your object. IE:
-(void)EventList
{
if (listOfEvents == nil) {
listOfEvents = [[NSMutableArray alloc] init];
}
[listOfEvents addObject:#"ran"];
NSLog(#"%#",listOfEvents);
}
In Objective-C, messages with void return types sent to nil go to absolutely-silent nowhere-land.
Also, for the sake of balance, be sure you have a [listOfEvents release] call in your dealloc implementation.
Apparently you're not initializing your array.
NSMutableArray *listOfEvents = [[NSMutableArray alloc] init];
If that's your problem, I suggest reading the docs again. And not the NSMutableArray docs. Go back to The Objective-C Programming Language and others.
You need to alloc the NSMutableArray. Try doing this first -
NSMutableArray *listOfEvents = [[NSMutableArray alloc] init];
After this you could do what you what you planned...

Why Do I Have to Create An Object and Assign It to A Property in Objective C?

So I had this code, and it did not work:
for (NSDictionary *item in data){
[self.resultsArray addObject:item];
}
self.resultsArray is nil. But then I changed it to this:
NSMutableArray *myDataArray = [[NSMutableArray alloc] init];
for (NSDictionary *item in data){
[myDataArray addObject:item];
}
self.resultsArray = myDataArray;
[myDataArray release];
and now it worked. self.resultsArray is now populated
So I'm a beginner in Objective C and I was wondering why can I not just directly use it in the property's addObject. Why did I have to create another mutable array, populate it, assign it to the resultsArray property and release the mutable array I made?
Thanks in advance!
EDIT: Also, in a lot of books I've been working on, this is done a lot.
simple answer
You didn't initialize self.resultArray before adding objects to it. It is just a pointer to the value which is nil until you alloc it.
self.resultArray = [[NSMutableArray alloc] init]; before adding objects to it will solve the issue.
However, this way of alloc'ing will create a memory leak, therefore it is not shown in books and examples. Memory leak can happen if the self.resultArray property is marked as retain and by calling alloc it will be retained 2 times.
If self.resultsArray is nil, then [self.resultsArray addObject:item] will NOT add an object to the array, it will just do nothing (because the array will be nil by default, and sending messages to nil is a no-op in Objective-C). When you create a mutable array as a local variable, you can add things to it — then if you assign it to the property, well, everything works as you expect and self.resultsArray will no longer be nil.
Typically when you have properties like this, you'd set them up in your init method:
- (id)init {
// ...
self.resultsArray = [NSMutableArray array];
// or access the ivar directly:
// _resultsArray = [[NSMutableArray alloc] init];
// ...
}
Then as soon as your object is initialized you'll be able to add things to the array. Again, if you don't do this, it will be nil by default, and [self.resultsArray addObject:item] will have no effect.
Chances are you are not initializing the array (I'm going to assume myDataArray is an NSMutableArray).
In your init method, call myDataArray = [NSMutableArray array]; and it'll work
The important thing to note is that you're not creating another mutable array as you didn't have an array to start with. Merely declaring a property or variable does not create an object to go along with it. That's why self.resultsArray starts out as nil.
The working code you have is designed to allow you to explicitly release the array as you are retaining it twice: once when you alloc it and once when you assign it to your property. You only want one of those retains, so you release once.
You could just do:
self.resultsArray = [[NSMutableArray alloc] init];
[self.resultsArray release];
for (NSDictionary *item in data){
[self.resultsArray addObject:item];
}
This is less code, but it's not as clear. Clarity is important.

NSMutableDictionary error

I want to use NSMutableDictionary to cache some data i will use later. My custom object is following:
#interface MyData : NSObject {
NSRange range;
NSMutableArray *values;
}
#property (nonatomic, retain) NSMutableArray *values;
and implement:
- (id)init {
if (self = [super init]) {
values = [[NSMutableArray alloc] init];
}
return self;
}
and when i wanna cache it, i use it like this:
NSMutableDictionary *cache = [[NSMutableDictionary alloc] init];
NSString *key = #"KEY";
MyData *data = [[MyData alloc] init];
// save some data into data
[data.values addObject:"DATA1"];
[data.values addObject:"DATA2"];
//... ...
[cache setObject:data forKey:key];
My questions is the count of cache.values is zero when i retrieve this object later as follow:
[cache objectForKey:#"KEY"];
i can retrieve "data" and the object's memory address is the same as the address when i put it into cache.
what's wrong? i need some kind guys help, any info is helpful. thanks
As Carl Norum pointed out, you're passing C strings to addObject:. addObject:, as its name suggests, requires a pointer to a Cocoa object; a C string is a pointer to characters. You need to pass NSString objects there; for literal strings, this simply requires prefixing them with #: "Fred" is a constant C string, whereas #"Fred" is a constant NSString object.
Is cache an instance variable? It looks like it's not; it appears to be a local variable, which means you're creating a new dictionary object every time. That's why there's nothing you've added previously (to previous dictionaries) in the new one. It also means you're leaking those previous dictionaries, since you're not releasing them (not in the code you showed, anyway).
Make cache an instance variable and only create the dictionary when you don't already have one (i.e., when cache == nil). Creating the dictionary in your init method is one good way. And make sure you manage its lifetime appropriately, so you don't leak and/or crash.
First of all your objects your adding don't look right it should have an # before the string. Like #"DATA1"
Second when you add an object to a dictionary or an array it does not make an actual copy of it. It just creates a pointer to it so if those objects are destroyed or moved somewhere also they are also gone out of your dictionary. A better way to make a cache of your values would be to copy the objects like so:
MyData* cache = [[MyData alloc] init];
for (int i = 0; i < [data.values count]; i ++){{
[cache.values addObject:[NSString stringWithString:[data.values objectAtIndex:i]]];
}
Don't use a dictionary in this situation.

Static Variable in Cocoa Class Category

I have a cocoa 'category' for adding inflections (pluralize, singularize, etc.) to NSString. The code requires loading a set of regular expression rules and exceptions from a PLIST into dictionaries and arrays, as well as adding manual exceptions from code. I need a way to persist these data structures (as class members) between multiple calls to the inflection code (all instance methods). I attempted:
+ (NSMutableArray *)uncountables
{
static NSMutableArray *uncountables = nil;
if (uncountables == nil) uncountables = [NSMutableArray array];
return uncountables;
}
However, it appears to fail occasionally. Does a good way of doing this exist? I don't want to subclass NSString if possible. Thanks.
[NSMutableArray array];
returns an autoreleased array. Use this instead:
[[NSMutableArray alloc] init];
I think this code is OK. I use the same thing a lot for singletons. But be aware that it is not thread safe this way. Maybe you calling it from different threads?
As drawnonward already mentioned, [NSMutableArray array]; returns an autoreleased array. But I don't think, it's a good idea to return non-autoreleased array, because it contradicts with Cocoa memory management conceptions - only alloc, copy and new should be released manually. All other initializations are autoreleased.
So, you should just use
interface:
NSArray *a;
...somewhere in a code...
a = [[NSString uncountables] retain];
...
- (void)dealloc {
[a release];
}
to get properly retained/released objects.