How manages the memory to use copied array and dictionary? - objective-c

I have removable data in Array (NSMutableArray)...(When data remove in array, array uses other place. so, I retain that.)
also, I used copy command....but I not found how release that.
NSMutableArray *arrRemovable;
NSMutableDictionary *dicData; (alloc, and init)
[_dicData setObject:[arrRemovable copy] forKey:#"DATA1"];
(it's already retain count 2)
I want not to make the arrRemovable variable..
i want to subtract retain count.
[[_dicData objectForKey:#"DATA1"] release]
I using that, but analysis tool warned me.
Message is "Incorrect decrement of the reference count of an object that is not owned at this point by the caller"
help me!!

You can do this:
NSMutableArray *copyOfArrRemovable = [arrRemovable copy];
[_dicData setObject:copyOfArrRemovable forKey:#"Data1"];
[copyOfArrRemovable release];
This is assuming I understood the question correctly. If not, please explain.
Hope that helps.

Related

Assign or retain in cocos2d and objective C

Here's my current situation:
I have a NSMutableArray named dictKeyArray which I assign a property with #property(nonatomic,retain)NSMutableArray *dictKeyArray
I synthesize my mutable array in the implementation file.
Later, I have a dictionary name storeDict. I assign all the keys of the dictionary to the dictKeyArray like so:
dictKeyArray = [[storeDict allKeys] mutableCopy];
Now I use this dictionary later in my implementation file. However, when it comes to releasing it, I release it once in my dealloc method. When checking with instruments, a leak shows up! Why is dictKeyArray leaking? Should I be using assign instead of retain?
I'm still not clear on what the difference is exactly...
thank you!
You have to send it an
[[[storeDict allKeys] mutableCopy] autorelease];
Just to make this clear: mutableCopy does the same as alloc meaning you are claiming ownership of the object in question. You have to decrease the retainCount by one.
By the way: You should use the accessor you wrote for it. You are just assigning it to your iVar at the moment. If you want to make your accessors work, you will have to use something like
object.dictKeyArray = ...;
in general. Or here (as mentioned by dreamlax)
self.dictKeyArray = ...;
because you are referring to an object of this specific class the code is in.
Only this way you are ensuring your object is properly retained by your accessor. Otherwise writing the accessor code doesn't make sense at all because it never gets called.
Please note: As Josh said in the comments, your code should be valid (at least from my point of view). What I suggested is a solution that is not as error-prone as yours because you adhere to the rules (could save you from headache in the near future).
You should be using self.dictKeyArray = .... Without the self. you are accessing the instance variable directly, bypassing any memory management benefits of properties, but, remember that you own the result of mutableCopy, and assigning to a property that also takes ownership will result in double-ownership, so use:
self.dictKeyArray = [[[storeDict allKeys] mutableCopy] autorelease];

how to initialise NSMutableArray

I have a loop which adds values to an NSMutableArray, however when I move on to the next batch I need to clear down and initialise the array to add the next lot of data and I thought using [jobList release] would do the trick but it doesn't. Could someone please let me know what I can use to reset the array after each iteration.
If you send -release to it, then it is likely, but not certain that the object will be deallocated and not cleared as you want it to be.
The solution is super-simple: Use the -removeAllObjects method:
for(id x in jobList) {
//...
}
[jobList removeAllObjects];
//...
You can simply use [jobList removeAllObjects];
Doing areleasemay cause the object to be deallocated if no other objects retain it, so you definitely don't want to do that.
To do a clear down useremoveAllObjects.
Using release will deallocate the object which you are accessing, and this is wrong. I think you are looking for
[jobList removeAllObjects];

Grow a NSMutableArray with NSNumber objects

Sorry for the newbie question, but I need a NSMutableArray with some NSNumber inside, created dynamically in a for cycle. My code looks like this:
for (...){
NSNumber *temp_number = [[NSNumber alloc] initWithInteger:someNSInteger];
[target_array addObject:[temp_number copy]];
[temp_number release];
}
Is this a correct way to do it? Does it leak?
Thanks! Miguel
Yep, that leaks. You want:
NSNumber *temp_number = [[NSNumber alloc] initWithInteger:someNSInteger];
[target_array addObject:temp_number];
[temp_number release];
So, no copy. The logic is that because you use alloc, you end up owning temp_number. You then add it to the array and the array does whatever it needs to. You've used temp_number for its intended purpose, so you no longer want to own it and release it.
If you were to take a copy, that would create another instance of NSNumber, which you also own, and therefore which you should also release when you're finished with.
In practice, the array (if it's allocated and exists, rather than being nil), will retain the object for itself, but that's an implementation detail specific to that class and not something you should depend upon or even be particularly interested in beyond the contract that says that the objects you add can later be found in the array.

Can someone please explain this one line of code on Objective-C?

eventPoints = [[NSMutableArray array] retain];
What does the "retain" keyword do along with the "array"?. "array" is not defined anywhere.
Also eventPoints was declared as a NSMutableArray.
I am just trying to learn. Thanks
Check out this question I asked: iPhone memory management (with specific examples/questions)
It took me a while to get a hang of this too. Hope this helps!
EDIT: As for what [NSMutableArray array] does, according to the docs on NSArray, it does this: "Creates and returns an empty array." and is used by mutable subclasses of NSArray, such as NSMutableArray. Basically, it's the same as doing: [[[NSMutableArray alloc] init] autorelease] (or something really similar). Because it's autoreleased, you need to call retain on it to keep the variable.
1) What does the "retain" keyword do along with the "array"?
As you know, objective-C uses referencing counting for memory management. "retain" increments 1 by everyPoints.
2) "array" is not defined anywhere.
"array" is defined in NSArray. NSMutableArray is a subclass of NSArray, so NSMutableArray can use functions defined in NSArray. "array" is a class method that creates and returns an empty array.
There are four ways to explicitly increment 1 in objective-c: alloc, copy, retain, attain
Because you create an empty array without using any of these, you manually increment 1 by "retain". So in the future, you might need to [everyPoints release] to decrement 1 to deallocate it.

Pass NSMutableArray object

I'm getting lost in pointer land, I believe. I've got this (code syntax might be a little off, I am not looking at the machine with this code on it...but all the pertinent details are correct):
NSMutableArray *tmp = [[NSMutableArray alloc] init];
I them pass that to a routine in another class
- (BOOL)myRoutine: (NSMutableArray *)inArray
{
// Adds items to the array -- if I break at the end of this function, the inArray variable has a count of 10
}
But when the code comes back into the calling routine, [tmp count] is 0.
I must be missing something very simple and yet very fundamental, but for the life of me I can't see it. Can anyone point out what I'm doing wrong?
EDIT: www.stray-bits.com asked if I have retained a reference to it, and I said "maybe...we tried this: NSMutableArray *tmp = [[[NSMutableArray alloc] init] retain]; not sure if that is what you mean, or if I did it right.
EDIT2: Mike McMaster and Andy -- you guys are probably right, then. I don't have the code here (it's on a colleague's machine and they have left for the day), but to fill the array with values we were doing something along the lines of using a decoder(?) object.
The purpose of this function is to open a file from the iPhone, read that file into an array (it's an array of objects that we saved in a previous run of the program). That "decoder" thing has a method that puts data into the array.
Man, I've totally butchered this. I really hope you all can follow, and thanks for the advice. We'll look more closely at it.
You don't need to call retain in this case. [[NSMutableArray alloc] init] creates the object with a retain count of 1, so it won't get released until you specifically release it.
It would be good to see more of the code. I don't think the error is in the very small amount you've posted so far..
I agree with Mike - based on the code you've posted, it looks correct. In addition to posting the code used to call the function and add items to the array, you could try checking the memory addresses of the pointer at the end of the function (when it has all of the objects), and also once it has returned (when it has no objects). I'm not sure why it would be different, but then again the items should stick in the array as well.
You need to show us a bit more of how you're adding objects to the array for us to really help.
I've seen a lot of people write code like this:
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
array = [foo bar];
People doing this think it "creates and then sets" a mutable array, but that's not at all what it does. Instead, it creates a mutable array, assigns it to the variable named array, and then assigns a different mutable array to that variable.
So be sure you're not confusing the variable for the object to which it is a reference. The object isn't the variable, it's interacted with through the variable.
NSMutableArray retains objects added to it, but have you retained the array itself?
The code you posted should work. You must be doing something funny in the decoder function.
You should not retain that array. It's automatically retained with init. If you retain it, you'll leak memory. If you are just starting with objective c, take time and read "Introduction to Memory Management Programming Guide for Cocoa". It will spare you lots of headache.
Why are you writing so much code to read an array from a file? It's already supported by the framework:
+ arrayWithContentsOfFile:
Returns an array initialized from the contents of a specified file.
The specified file can be a full or
relative pathname; the file that it
names must contain a string
representation of an array, such as
that produced by the
writeToFile:atomically: method.
So you can do this:
NSMuatableArray *myArray = [NSMutableArray arrayWithContentsOfFile:#"path/to/my/file"];
This is a convenience method, so the object will autorelease. Make sure to retain this one if you want to keep it around.