Obj-C: A reference or a copy? - objective-c

Is the product item a copy, or just a reference to the object in the NSArray? Does it need to be released? Considering there is no alloc, I assume there is no need for release, correct?
ProductItem *item = [appDelegate.productTextList objectAtIndex:[indexPath row]];

It is a pointer to the ProductItem class.
You should only release an object if you have done something to increase it's retain count. I.e. alloc/init, copy, or call retain.

It's just a pointer of type ProductItem, so it's not a copy.
Your reference is guaranteed to be valid in the scope of the call to objectAtIndex (it calls autorelease on the object). If you want to keep it around for longer you need to retain and are responsible to release it when you are done with it.

Related

About retain/release for properties

I have this in my .h file:
#property (nonatomic,retain) CCTexture2D *tempScreenshot;
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Do I have to release tempScreenshot in the dealloc method of my class?
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
Since you're saying "retain" I am assuming this is manual memory management code. If at all possible, you should switch to automatic reference counting (ARC). It dramatically simplifies this work and is faster than the equivalent manual code. Other than support for older OSes, there is almost never a reason to do manual memory management anymore.
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Whenever you call [self setTempScreenshot:], the accessor will retain the parameter and release the old value. Assigning the ivar directly will not give you any of this. You should always use the accessor except in init and dealloc.
Do I have to release tempScreenshot in the dealloc method of my class?
Yes.
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
It will be released as long as you use the accessor.
The retain keyword marks the property as retain upon assignment, meaning that on a set, retain will be called on the new value, and release will be called on the old value.
You will need to release the object on dealloc.
In your dealloc method, do: self.tempScreenshot = nil;
This will cause the object to be released. It will then be deallocated assuming nothing else has retained it.
If you were to write your own setter method to retain an object it would look like this.
//Assume an instance variabled name obj for this example
- (void)setAndRetainObjectExample:(NSObject *)newObj {
[obj release];
obj = newObj;
[obj retain];
}
Using the synthesized methods is much cleaner, but looking at it this way may clear up any confusion.

Does stringWithFormat create a retain +1 instance?

I'm declaring an ivar of type NSString on a class. To initialize the value of this ivar I use the following code:
NSString *myVar;
-(void)inAnyMethod
{
myVar = [NSString stringWithFormat:#"%#",theValue];
}
Do I have to release this ivar? According to my understanding, it is not my responsibility. But in most cases, strings that I use in this manner cause leaks.
What am I missing?
You do not have to release it, because that is a convenience method that returns an autoreleased object.
The way to know if you are getting something with a retain count of 1 that you will need to release is using the Cocoa naming conventions which say that anything that starts with new, alloc or contains copy in the method name will return a retain 1 object, the others will return autoreleased objects like in this case.
In addition to Oscar Gomez answer, note that when you use class methods (those methods with plus sign that you can find in the documentation and are not included in Oscar Gomez list, e.g. stringWithFormat is one of them), you have not to worry about memory management. If you create your own class method, you should do the same: return an autorelease object.
Regarding your code, it cannot work if you simply assign your ivar to the NSString object (returned from that method). In fact, at some point of your application cycle, the object will be released (it has been put in a pool) and your ivar will not reference any object anymore.
The trick: create a #property with a copy policy or send a copy message like the following:
myVar = [[NSString stringWithFormat:#"%#",theValue] copy];
Copy is normally used when a class has subclasses of mutable type. Otherwise use retain. Once done, you have the possession for that object and you have to remember to release it. If you don't do it you cause a leak.
[myVar release];
P.S. Since Xcode 4.2 there is a new compiler feature called ARC.
Hope it helps.

Releasing objects created by functions

I'm learning obj-c and I have a question about memory management:
Say I have a function that returns an NSDictionary, "fDictionary",
NSDictionary *fDictionary {
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], #"blah",nil];
return dict
}
that is called by a particular method:
-(int)fNumber {
NSDictionary *f = fDictionary();
return [[f objectForKey:#"blah"] intValue];
}
What I'm unclear about is how/where I should be releasing the NSDictionary object.
Should I release it in the method, or autorelease it in the function?
If the function was written properly, the dictionary is autoreleased, so you don't have to release it at all. It will be released soon, by the autorelease pool.
You only release what you yourself retain or copy. These are the things you "own". Be sure not to release them too early. The usual point is before the end of the function they are allocated or retained in, if they are local. If they are ivars, the best point is, usually, the dealloc of the class to which the ivar belongs.
Without knowing anything about fDictionary it's difficult to be sure, but the convention followed in most Object C code is as follows:
You own it if the instance was created with an alloc or copy
You own it if you retain it
Otherwise you don't own it
If you don't own it you should not release it.
So by convention, the function would return an autoreleased object and you wouldn't need any extra management in your method.
The general rule is if your code alloc's something, you need to release or auto-release it.
If this was someone else's function, you would expect that the returned dictionary was autoreleased - which is the convention here. I would ensure that fDictionary returns an autoreleased NSDictionary.
If you have received an object from a method which name begins with “alloc”, “new”, “copy”, or “mutableCopy”, you have to release or auto-release it. Otherwise it is already autoreleased.
If you have retained something, you have to release it, nothing else will do that for you.
Every Obj-C programmer must read Memory Management Guide.
No.
NSDictionary dictionaryWithObjectsAndKeys: (which is really just [[[NSDictonary alloc]initWithObjectsAndKeys:, nil]autorelease]) returns an autoreleased NSDictionary. This means the dictionary will automatically be released when the computer decides it is no longer needed.
If in fDictionary() the dictionary was alloced, you would need to release it manually. It is a rule of thumb to always return autoreleased objects from functions/methods, so the user of the functions/methods does not have to worry about memory management.

Reference on when to release in Objective-C

I'm having a recurring problem in Objective-C. I'm either releasing things too many time, or not enough. or perhaps I'm not retaining them enough...
Can someone point me at a good reference that will give me a rule of thumb on when I need to retain and release?
For example:
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
if I alloc an object and only need it in that method, do I need to release it? retain it?
Obviously, if I retained something, I needtorelease it, but beyond that, I get a bit lost.
The rules are generally pretty simple. If you get an object in one of the following ways:
id obj = [[MyObject alloc] init];
id obj = [myObject retain];
id obj = [myObject copy];
id obj = [myObject mutableCopy];
then you need to release it at some point -- in the same method, or your dealloc method, generally. In other words, balance your calls to alloc, retain, copy, and mutableCopy with a matching release call.
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
This happens rarely. The documentation for the called method should specify that you are responsible for releasing the returned object; otherwise, you should assume you're receiving an autoreleased object.
if I alloc an object and only need it in that method, do I need to release it? retain it?
Yes, you need to release it (but you don't need to retain it). (You can also use one of the convenience methods that return an autoreleased object if you're only going to use it in that method.)
There is one and only one canonical reference: Apple's Memory Management Guide for Cocoa or iPhone.

Do removeAllObjects and release of an NSMutableArray both have the same functionality?

I have written the following line of code:
NSMutableArray *array=[[NSMutableArray alloc]init];
This allocates some memory. My question is, how can we later release this memory, whether using removeAllObjects method or [array release]?
Do both methods have the same functionality?
When you add an object to the array, the object's retain count will increase by 1. When you remove that object from the array, retain count will decrease by 1 to balance it out. But if you release the array, all objects will automatically receive a release message. So you don't need to call removeAllObjects before releasing the array.
Technically, these two method are not same. If you call removeAllObjects, the array will become empty and all objects will receive a release message but the array itself is still not released. The array will be released when you call release on it.