This question already has answers here:
NSMutableArray addObject not working
(2 answers)
Cannot add object to an NSMutableArray array
(2 answers)
Closed 10 years ago.
I think, I am doing a pretty basic mistake, but I am using an NSMutableArray and this somehow doesn't add the object, I'm sending it its way. I have a property (and synthesize)
#property (nonatomic, strong) NSMutableArray *kpiStorage;
and then:
ExampleObject *obj1 = [[ExampleObject alloc] init];
[kpiStorage addObject:obj1];
ExampleObject *obj2 = [[ExampleObject alloc] init];
[kpiStorage addObject:obj2];
NSLog(#"kpistorage has:%#", [kpiStorage count]);
and that always returns (null) in the console. What am I misunderstanding?
Make sure you allocated memory for kpiStorage.
self.kpiStorage = [[NSMutableArray alloc] init];
On top of forgetting to allocated memory for your NSMutableArray, your NSLog formatting is also wrong. Your app will crash when you run it. The following changes are needed
You will need to add
self.kpiStorage = [[NSMutableArray alloc] init];
and change your NSLog to the following
NSLog(#"kpistorage has:%d", [self.kpiStorage count]);
If you are not using ARC make sure you should not create a memory leak in your project. So better way would be allocating like this
NSMutableArray *array = [[NSMutableArray alloc] init];
self.kpiStorage = array;
[array release];
make it a habit to do not directly do
self.kpiStorage = [[NSMutableArray alloc] init];
in this case your property's retain count is incremented by 2. For further reading you can stydy Memory Leak when retaining property
Related
Hi I'm trying to loop through an array of objects in an array to try and assign them an value. Im doing this through fast enumeration but when I run the build it succeeds but crashes and points to this line:
for (SKSpriteNode* var in objects_array)
. Did i mess up the syntax? I'm still new to objective-c. It tells me that var is unused and when i run the build that point is a breakpoint.
(btw I didn't include the code for when I created the actual SKSpriteNode objects left middle and right because they have multiple properties and i thought it may be distracting. I can post it though if needed)
Thanks!
NSMutableArray* objects_array = [[NSMutableArray alloc] init];
NSMutableArray* value_array = [[NSMutableArray alloc] init];
[objects_array addObject:#"left"];
[objects_array addObject:#"middle"];
[objects_array addObject:#"right"];
for (SKSpriteNode* var in objects_array) {
int value =arc4random_uniform(1);
[value_array addObject:[NSNumber numberWithInt:value]];
}
You have two problems. The first one was said by Rory; you forgot to initialize your variables:
NSMutableArray* objects_array = [[NSMutableArray alloc] init];
NSMutableArray* value_array = [[NSMutableArray alloc] init];
The second problem is that you are working with different variables. Here you say that you are working with NSString*:
[objects_array addObject:#"left"];
[objects_array addObject:#"middle"];
[objects_array addObject:#"right"];
And here you say that you are working with SKSpriteNode*:
for (SKSpriteNode* var in objects_array)
If your sprites are called left, middle and right, you should do this to initialize them (for example):
[SKSpriteNode spriteNodeWithImageNamed:#"left.png"];
And in that case, that should be your for:
for (NSString* var in objects_array)
You need to initialise the arrays:
NSMutableArray* objects_array = [[NSMutableArray alloc] init];
NSMutableArray* value_array = [[NSMutableArray alloc] init];
In my application i have enabled the ARC. But in my application following lines gives me memory leaks according to instruments. It is in ios 7.0.
-(id)init{
variables = [[NSMutableArray alloc] init]; // Leak
events = [[NSMutableArray alloc] init]; //Leak
return self;
}
Update
But in my app if i do something like below it does not show me any leak. But i can't add items in to the variables.
-(id)init{
variables = [[[NSMutableArray alloc] init] copy]; // No Leak
events = [[[NSMutableArray alloc] init] copy]; //No Leak
return self;
}
--
NSString *utfString =[NSString stringWithUTF8String:(const char *)attr->children->content];//Leak
--
-(NSObject*)createObjectForClass:(NSString*)className{
Class cls = NSClassFromString(className);
NSObject *object = [[cls alloc]init]; //Leak
if(cls != nil){
CFRelease((__bridge CFTypeRef)(cls));
}
return object;
}
Does anyone has any idea how to fix this?
My guess right now is that your entire object is leaking, which means that the NSMutableArrays created in -init also leak. The version that calls copy isn't leaking because the copy is probably returning a singleton instance of NSArray (as there are zero elements in it, and it's an immutable NSArray, there's probably a singleton instance for that).
arrayOfElements = [NSMutableArray arrayWithArray:[someObj getArray]];
and
arrayOfElements = [[NSMutableArray alloc] init];
arrayOfElements = [someObj getArray];
What's the difference?
The first arrayOfElements does not seem to lose its objects when it returns count in numberOfRowsInSection:(NSInteger)section, but the second one does. I get EXC_BAD_ACCESS when I do it the second way.
EDIT:
Can I suppose now that this is the best way,
arrayOfElements = [[NSMutableArray alloc] initWithArray:[someObj getArray]];
because I am initializing an array with the contents of whatever will be autorelease'd, and I now have a fully independent array in the current class, that is viewDidLoad, oops sorry, ViewController.
This line creates an NSMutableArray from an existing array
arrayOfElements = [NSMutableArray arrayWithArray:[someObj getArray]];
This combination first creates an NSMutableArray and then instantly discards it replacing it with what is returned by [someObj getArray]
arrayOfElements = [[NSMutableArray alloc] init]; // Create new NSMutableArray
arrayOfElements = [someObj getArray]; // Throw away the newly created array and replace with the result of [someObj getArray]
If you are not using ARC then it is purely by luck that either would work.
In both cases arrayOfElements is being assigned an autorelease'd object - which will be cleared soon (most likely the next runloop). It is only by chance that nothing else has been written over this point of memory which allows one of your implementations to still work.
If you are not using ARC then really you should update your project to be using it will handle a lot of cases like this for you.
You should definitely be using properties (not bare ivars) as this will help reduce memory issues (for non-ARC) and give a more consistent interface to your code.
In your header (or class extension) declare the property like this
#property (nonatomic, strong) NSMutableArray *arrayOfElements;
Now for ARC you can simple do
[self setArrayOfElements:[[someObj getArray] mutableCopy];
for non-ARC you can do
NSMutableArray *array = [[someObj getArray] mutableCopy];
[self setArrayOfElements:array];
[array release]; array = nil;
Also note that getArray is a bad method name.
The use of “get” is unnecessary, unless one or more values are returned indirectly.
Coding Guidelines
When you are adding objects to mutable array from another array, try this:
[arrayOfElements addObjectsFromArray: [someObj getArray]];
If you're not using ARC, you need to make sure its retained.
if (arrayOfElements) {
[arrayOfElements release];
}
arrayOfElements = [[NSMutableArray alloc] initWithArray:[someObj getArray]];
What is the difference between
NSMutableArray* p = [[NSMutableArray alloc] initWithObjects:...]
and
NSMutableArray* p = [NSMutableArray arrayWithObjects:...]
In the first one, you have the ownership of array object & you have to release them.
NSMutableArray* p = [[NSMutableArray alloc] initWithObjects:...];
[p release];
& last one you dont need to release as you don't have the ownership of array object.
NSMutableArray* p = [NSMutableArray arrayWithObjects:...]; //this is autoreleased
If you call release in this, then it will crash your application.
[NSMutableArray arrayWithObjects:] is the same as [[[NSMutableArray alloc] initWithObjects:] autorelease]
In practice, there is no difference if you're on ARC.
The latter basically is just a shorthand for [[NSMutableArray alloc] initWithObjects: ...], except the returned array is autoreleased (which is important if you're still doing manual reference counting).
What I think the difference is that: initWithObjects is a instance method, and arrayWithObject is a class method.
I am from android background and I just started working on iPhone
I want to perform this operation in iPhone as I do in Android.
ArrayList<String> aa = new ArrayList<String>();
public void fillArray(String s)
{
aa.add(s);
}
As Binyamin Sharet suggest you have to use NSMutableArray. This class allows you to create a dynamic array. You can perform addition or deletion. On the contrary NSArray is a immutable version of it. You cannot add or delete objects to a NSArray once created.
The same distinction can be applied to NSDictionary and NSMutableDictionary (and other).
Here a simple example.
NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:#"first string"];
[arr addObject:#"second string"];
An important aspect of NSMutableArray (the same could be applied to other class) is the memory management one. When you add an object to a NSMutableArray it retains objects added to it. So, if you NOT use ARC you have to deal with this aspect.
NSMutableArray* arr = [[NSMutableArray alloc] init];
id obj = [[NSObject alloc] init]; // a general object
[arr addObject:obj];
[obj release];
For further info I suggest you to read about NSMutableArray class reference.
Hope it helps.