Acceptable ways to release a property - objective-c

Assume there is a class with the following interface:
#import <Foundation/Foundation.h>
#interface MyClass : NSObject {
}
#property (nonatomic, retain) NSDate* myDate;
-(void)foo;
#end
and the following implementation:
#import "MyClass.h"
#implementation MyClass
#synthesize myDate = _myDate;
- (void)dealloc
{
[_myDate release];
[super dealloc];
}
-(void)foo
{
NSDate* temp = [[NSDate alloc] init];
self.myDate = temp;
[temp release];
}
#end
1) In the function foo will releasing like this ensure that the retain count of the objects is properly maintained (i.e. no memory is leaked and no unnecessary releases are performed).
NSDate* temp = [[NSDate alloc] init];
self.myDate = temp;
[temp release];
2) Same question as in 1) except applied to the following technique:
self.myDate = [[NSDate alloc] init];
[self.myDate release]
3) Same question as in 1) except applied to the following technique:
self.myDate = [[NSDate alloc] init] autorelease];
4) Same question as 1) but applied to the following technique:
self.myDate = [[NSDate alloc] init];
[_myDate release]
5) Same question as 1) but applied to the following technique:
[_myDate release];
_myDate = [[NSDate alloc] init];

1) Just fine.
2) Possibly unsafe, and will trigger warnings in the latest LLVM static analyzer. This is because the object returned by the getter method may not be the same one you passed to the setter. (The setter may have made a copy, for example, or may have failed validation and set a nil instead.) This would mean you were leaking the original object and over-releasing the one the getter gave back to you.
3) Just fine; similar to 1 but the release will come when the current autorelease pool is drained instead of immediately.
4) Possibly unsafe, but will not trigger warnings that I've seen. The issue is similar to the one described in 2; the object in the ivar may not be the one you passed to the setter.
5) Safe, but will not use the setter method or notify any observers of the property.
In the case where the property is a retain type, and both the getter and setter are just the synthesized versions, all of the above examples will work. However, they don't all represent best practice, and may trigger analysis warnings. The goal should be that the -foo method works correctly regardless of how myDate is managing its memory. Some of your examples above don't do that.
If, for example, you decided to change the property to copy later, you should not be required to change any other code to make it work correctly. In cases 2 and 4, you would be required to change additional code because the foo method is assuming that the setter will always succeed and always set the original object.

5) is a bug - it leaks the old instance as it doesn't get released but just reassigned.
1) is clean and the best way to go.
4) is ok but puts some burden on the memory system - the object might live longer than needed.
2) technically ok, but you shouldn't directly retain/release the property - that's what the syntactic sugar is for!
3) technically ok, but also bypasses the property and relies on implementation details.
2) and 3) are discouraged and ask for trouble in the future when some part of code changes.
Edit: New code doesn't leak in 5). It has the same downsides, though.
There's a reason why we got support for properties, and it does a great and consistent use. You should only consider bypassing them if your time profile gives very clear hints that this is a bottle neck (unlikely).

First, if you want to avoid the alloc, release, autorelease etc... you can call a date factory method which doesn't start with alloc.
For example:
self.myDate = [NSDate date];
The date class factory method does an autorelease according to the convention rules. Then the property retains it.
Alloc will give it a retain count of 1, then assigning the property will retain it. Since your class is now retaining it from the property, you can release it to counter act the alloc.
Ditto but that's a wierd round about way to do it.
3 is equivalent to the code I had above ([NSDate date]);
In this case, the property will retain it (after alloc incremented the retain count), then you're going under the covers to decrement it. Works but I wouldn't recommend doing that since you're synthesized (retain) property will do that for you.

the pattern of release and renew is merely a semantic. You get a retain count for each of the following.
myObject = [Object alloc]
objectCopy = [myObject copy]
myNewObject = [Object newObjectWithSomeProperties:#"Properties"] // Keyword here being new
// And of course
[myObject retain]
a property with the modifier (retain) or (copy) will have retain count on it.
the backing store _myDate is merely where the object is actually stored.
when you get a retain count you need to release.
Either immediately with the [myObject release] message or let the pool release it with [myObject autorelease]
Whatever the case, Any retain you are given (implicit or explicit) will need to be released. Otherewise the garbage collector will not collect your object and you will have a memory leak.
the most common usage in
Object myObject = [[[Object alloc] init] autorelease]; // Use this when you dont plan to keep the object.
Object myObject = [[Object alloc] init];
self.myProperty = [myObject autorelease]; // Exactally the same as the Previous. With autorelease
// Defined on the assignment line.
self.myProperty = [[[Object alloc] init] autorelease]; // Same as the last two. On one line.
I will demonstrate other possibilities
// Uncommon. Not incorrect. But Bad practice
myObject = [[Object alloc] init];
self.myProperty = myObject;
// Options
[_myProperty release] // Bad practice to release the instance variable
[self.myProperty release] // Better practice to Release the Property;
// releasing the property or the instance variable may not work either.
// If your property is using the (copy) modifier. The property is copied rather then retained.
// You are still given a retain count.
// But calling release on a copy will not release the original
[myObject release]; // Best Practice. Good when Threading may run the autorelease pool
[myObject autorelease]; // As good as the previous.
// But may leave your object in memory during long operations
Essentially, your object given a retain will be the same object in the Property the Variable and the Instance Variable. Releasing on any of them will release it.
However. Best practice says that if you retain an object. Best to call release on the same variable of that object. Even if Autorelease and retain is called on the other side.
// Other items that give you a retain count.
Core Media or Core Anything Functions that have Create Or Copy in the name.

Related

Objective C: Newbie question about allocation, retain and release [duplicate]

This question already has answers here:
Objective-C: alloc of object within init of another object (memory management)
(3 answers)
Closed 8 years ago.
New to OC, many years of C, C++, C#, mind is kind of boggled now.
Given:
// AnInterface.h
#interface AnInterface : NSObject
{
}
#property (retain) SomeObject* m_Object;
// AnInterface.m
#import "AnInterface.h"
#synthesize m_Object;
-init
{
self= [super init];
if(!self)
return (nil);
SomeObject* pObject= [[SomeObject alloc] init];
self.m_Object= pObject;
[pObject release];
}
I am pretty sure the above is correct. However,
why not just do:
self.m_Object= [[SomeObject alloc] init];
Does that work as well? Is it in violation of some memory management tenet? It seems like it should work, one line rather than three, but I am certain I must be missing something....
Any insight would be appreciated.
The reason is because you defined the property m_Object to retain so it would result in a memory leak because alloc/init call results in a retain of +1 then property will retain giving it at least a retain count of +2. If you would like to make it one line feel free to abuse the auto release pool.
self.m_Object= [[[SomeObject alloc] init] autorelease];
That leaks the object. Since alloc returns an owning reference, and retain claims ownership a second time, you need to call release to balance the alloc or the object will think you want to hold onto it forever and never be deallocated.
self.m_Object = [[SomeObject alloc] init];
This causes an over-retain. You get one claim of ownership for the alloc, and another through the setter, which is declared as retaining the new value. Since you only have one pointer to the new value, you have too many claims. When the setter is used again:
self.m_Object = anotherObject;
the original object will receive only one release message, and you will lose the pointer. Since you had two claims on the object, it will not be deallocated, and you will have a leak.
The property access: self.m_Object = obj; is translated by the compiler into [self setM_Object:obj];. That is, the setter method for the property, created by the #synthesize directive, is called. That setter method retains its argument. The other option is to use the ivar directly in your init method:
-init {
//...
m_Object = [[SomeObject alloc] init];
//...
}
then you have only one claim on this object, caused by the use of alloc. Since you also have one reference to the object, this is correct.

iOS: Properties – allocating and releasing objects

I am struggling in iOS (4) with allocating objects in one scope and releasing it in another scope. I am using properties as pointers to the objects. The object is allocated and initialized in one instance class method and I release it in the class’ dealloc method. The properties are declared with retain. Besides having problems with using properties likes this I also find it cumbersome to alloc and initialize the object and set the property.
NSObject *object = [[NSObject alloc] init];
Self.myProperty = object;
[object release];
I tried
self.myObject = [[NSObject alloc] init];
However that gave me a memory leak.
My question: Do I have to make this temporary object or is there a more elegant way of doing this?
A followup question: Do I have to both set the property to nil and release the autogenerated ivar?
[self setMyProperty:nil], [myProperty release];
When XCode 4 generates property stubs for you it puts [self setMyProperty:nil] in viewDidUnload and [_myProperty release] in dealloc.
First question:
autorelease is your friend:
self.myObject = [[[NSObject alloc] init] autorelease];
Second question:
No, it's redundant, but harmless since the second operation will do nothing ([nil release] is safe).
I'd advise using the self.XXX = nil; construct, as it's safer and very clear/readable.
The self. notation is running through the synthesized setter which does a retain, which is why you need to do the autorelease on the init object. Conversely, you could leave off the self. and just use
myObject = [[NSObject alloc] init;
This line just sets the myObject pointer to the retained object, and you would not have any leak.
Here was my question from a while back along the same lines as yours:
MKReverseGeocoder autorelease/release question in Apple's CurrentAddress sample

Use autorelease when setting a retain property using dot syntax?

I see in some sample code that autorelease is used. I am not familiar with the instances when this is required. For example, if I create an annotation object
Header file
#interface someViewController: UIViewController
{
Annotation *annotation;
}
#property (nonatomic, retain) Annotation *annotation;
#end
Implementation file
#implementation someViewController
#synthesize annotation
#end
Question: Is it the correct approach if I initialize my annotation object in the implementation file like this?
self.annotation = [[Annotation alloc] initWithCoordinate:location];
Do I need to set autorelease for this? Or can I just do it the normal way and add the release in the dealloc method?
this is correct:
self.annotation = [[[Annotation alloc] initWithCoordinate:location] autorelease];
because annotation property is declared as a retain property, so assigning to it will increment its retain count.
you will also need, all the same, to release self.annotation in -dealloc.
in short:
init will set retain count to 1;
assigning to self.annotation, will set it to 2;
autorelease will set it back to 1 when the main loop is executed again;
release in dealloc will set the retain count to 0, so that the object will be deallocated);
the best way to think of autorelease is the following, in my opinion: autorelease will "schedule" an "automatic" release for your object at some (near) point in future (typically when the control flow goes back to the main loop, but details are hidden in the hands of Apple).
autorelease is mostly useful in conjunction with init, specifically in the following cases:
when you init a local variable, so that you don't have to release it explicitly before it goes out of scope (the main loop will do that for you);
when you return a pointer to an object you have just created without keeping ownership of it (typical case of the create/make* kind of selectors, the receiver is required to retain it to get ownership);
with properties that retain, when you assign to them an object that they should own uniquely;
with data structures that increment the retain count (NSMutableArray, NSMutableDictionary, etc): you should generally autorelease a newly inited object when you add it to such data structure.
apart from case 2, it is evident that the use of autorelease is meant to improve readability of the code and reduce the potential for errors (meaning that in all of the other cases, you could simply release explicitly your object after the assignment or at the end of the scope).
when using properties, you have always to check whether they are of the retain or assign/copy case; in the first case, assigning a newly inited object to a property generally requires autorelease.
Anyway, I would suggest at least skimming one of the many tutorial on memory management for iOS.
Autorelease is telling the object to release itself before leaving the scope.
Sometimes when you code, you'll encounter something like this
- (void)doSomething
{
if(true)
{
NSString *foo = [[NSString alloc] initWithString:#"foo"];
//Some execution here
[foo release];
}
}
- (void)doSomething
{
if(true)
{
//By doing this is telling to to release foo object before getting out of the scope
//which is similar with above practice
NSString *foo = [[[NSString alloc] initWithString:#"foo"] autorelease];
//Or you can do it this way
NSString *foo = [[NSString alloc] initWithString:#"foo"];
[foo autorelease];
//Some execution carry on, it'll release foo before entering next scope
}
//This is out of the scope
}
Of course, releasing an object doesn't mean deallocating the object.
Sometimes you retain the object so you can still use it outside of its scope.
Judging from your question, if your the object is located within your header file/interface.
You should release it in dealloc method. CMIIW.

ivars and how to properly instantiate their values (iPhone)

I have been developing an app for a while and now I have gotten to the "Instruments-Leaks" part.
I remember a thing that puzzled me about ivars a few months back when I was learning. I took the whole thing a bit on faith and just followed the way Apple and others did it. As far as I can read, the accessors generated by the SDK will take care of the memory management.
But how are ivars themselves initialized?
If I have an ivar like this in my interface;
#interface
{
NSArray *results;
}
#property(nonatomic, retain) NSArray *results;
#end
#implementation
#synthesize results;
If I during run time try to do this:
[self setResults:allReadyInitializedArray];
It will crash, telling me that this result object was not initialized. If I however do this:
self.results = [[NSArray alloc] init]; //Im assigning this property memory, but hasn't the SDK already done that?
[self setResults:allReadyInitializedArray];
it will work but it will apparently leak memory.
I was under the impression that using the generated
accessors would release the old value before setting the new, meaning
the above ought to come out with the old value released and the new with a +1 retain count.
Does it specifically have to do with the ivar being of type NSArray/NSMutableArray, I can't recall it has been a problem with other ivars.
The problem has been particular prominent in my XML parser, where I continuously need to set an ivar value, use it, overwrite this value, use the new value etc.
Would someone please help me outline the correct way "of going from": #property() -> #synthesize -> using the ivar -> to dealloc?
I have read the memory management documents, I have tried looking for some in debt documentation that was within my understanding, but it seems that even though I use ivars on a daily basis I don't understand what goes on behind the scenes.
All ivars initially set to nil so you need to instantiate them before use. It is really hard to say why setResults may produce errors without seeing its implementation.
self.results = [[NSArray alloc] init];
Here you create new array object using alloc method - its retain count equals 1. After that your setter method retains your array once more and so your 1st objects retain remains "unhandled" resulting in memory leak. To remove leak you can rewrite your code like:
self.results = [[[NSArray alloc] init] autorelease];
// or
self.results = [NSArray arrayWith...]; // any NSArray's convenience method that returns autoreleased object.
My understanding is that
self.results = anArray;
is the same as
[self setResults:anArray];
just because results is a property in this case.
The way setResults: is implemented is set by the #property (in this case it will retain the new value). So this means anArray will have a retain count of 1. After setting self.results, anArray will have a retain count of 2. This is why you want to release the previously used anArray.
That said, I don't understand why setResults: crashes when you're setting it. (Maybe it just crashes only when you try to use self.results, instead of setting it?)
I'm just a beginner myself, if something is wrong I strongly encourage everyone who reads this to let me know what is wrong or correct. Still learning this myself.
The way Apple would do this:
In the .h file
#property (nonatomic, retain) NSArray *results
In the .m file
#synthesize results;
- (id)init {
NSArray *anArray = [[NSArray alloc] init]; // retainCount = 1
self.results = anArray; // retainCount = 2
[anArray release]; // retainCount = 1, only one "left" is in self.results
}
- (void)dealloc {
[results release];
}

Why does this create a memory leak (iPhone)?

//creates memory leak
self.editMyObject = [[MyObject alloc] init];
//does not create memory leak
MyObject *temp = [[MyObject alloc] init];
self.editMyObject = temp;
[temp release];
The first line of code creates a memory leak, even if you do [self.editMyObject release] in the class's dealloc method. self.editMyObject is of type MyObject. The second line incurs no memory leak. Is the first line just incorrect or is there a way to free the memory?
The correct behavior depends on the declaration of the editMyObject #property. Assuming it is delcared as
#property (retain) id editMyObject; //id may be replaced by a more specific type
or
#property (copy) id editMyObject;
then assignment via self.editMyObject = retains or copies the assigned object. Since [[MyObject alloc] init] returns a retained object, that you as the caller own, you have an extra retain of the MyObject instance and it will therefore leak unless it there is a matching release (as in the second block). I would suggest you read the Memory Management Programming Guide[2].
Your second code block is correct, assuming the property is declared as described above.
p.s. You should not use [self.editMyObject release] in a -dealloc method. You should call [editMyObject release] (assuming the ivar backing the #property is called editMyObject). Calling the accessor (via self.editMyObject is safe for #synthesized accessors, but if an overriden accessor relies on object state (which may not be valid at the calling location in -dealloc or causes other side-effects, you have a bug by calling the accessor.
[2] Object ownership rules in Cocoa are very simple: if you call a method that has alloc, or copy in its signature (or use +[NSObject new] which is basically equivalent to [[NSObject alloc] init]), then you "own" the object that is returned and you must balance your acquisition of ownership with a release. In all other cases, you do not own the object returned from a method. If you want to keep it, you must take ownership with a retain, and later release ownership with a release.
Your property is declared "retain" meaning that it the passed in object is automatically retained.
Because your object already had a reference count of one from alloc/init there's then two references and I'm assuming only one release (in your destructor).
Basically the call to self.editMyObject is really doing this;
-(void) setEditMyObject:(MyObject*)obj
{
if (editMyObject)
{
[editMyObject release];
editMyObject = nil;
}
editMyObject = [obj retain];
}
By convention in Cocoa and Cocoa-touch, any object created using [[SomeClass alloc] initX] or [SomeClass newX] is created with a retain count of one. You are responsible for calling [someClassInstance release] when you're done with your new instance, typically in your dealloc method.
Where this gets tricky is when you assign your new object to a property instead of an instance variable. Most properties are defined as retain or copy, which means they either increment the object's retain count when set, or make a copy of the object, leaving the original untouched.
In your example, you probably have this in your .h file:
#property (retain) MyObject *editMyObject;
So in your first example:
// (2) property setter increments retain count to 2
self.editMyObject =
// (1) new object created with retain count of 1
[[MyObject alloc] init];
// oops! retain count is now 2
When you create your new instance of MyObject using alloc/init, it has a retain count of one. When you assign the new instance to self.editMyObject, you're actually calling the -setEditMyObject: method that the compiler creates for you when you #synthesize editMyObject. When the compiler sees self.editMyObject = x, it replaces it with [self setEditMyObject: x].
In your second example:
MyObject *temp = [[MyObject alloc] init];
// (1) new object created with retain count of 1
self.editMyObject = temp;
// (2) equivalent to [self setEditMyObject: temp];
// increments retain count to 2
[temp release];
// (3) decrements retain count to 1
you hold on to your new object long enough to release it, so the retain count is balanced (assuming you release it in your dealloc method).
See also Cocoa strategy for pointer/memory management
The first version creates an object without a matching release. When you alloc the object, it means you are an owner of that object. Your setter presumably retains the object (as it should), meaning you now own the object twice. You need the release to balance the object creation.
You should read the Cocoa memory management guide if you plan to use Cocoa at all. It's not hard once you learn it, but it is something you have to learn or you'll have a lot of problems like this.
Everyone else has already covered why it causes a memory leak, so I'll just chime in with how to avoid the 'temp' variable and still prevent a memory leak:
self.editMyObject = [[[MyObject alloc] init] autorelease];
This will leave your (retain) property as the sole owner of the new object. Exactly the same result as your second example, but without the temporary object.
It was agreed and explained that the code below does not have a leak
(assuming #property retain and #synthesize for editMyObject) :
//does not create memory leak
MyObject *temp = [[MyObject alloc] init];
self.editMyObject = tempt;
[temp release];
Question : is anything wrong with the following code that does not use a temp pointer ?
//does not create memory leak ?
self.editMyObject = [[MyObject alloc] init];
[editMyObject release];
To me this looks ok.