gorgi93
gorgi93

Reputation: 2535

objective c memory manegment when returning objects from another object

I am having problem with understanding one concept of memory managment, because I am new to objective C. For instance lets say I have a class Bar and Foo.

in main function I call:

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];

I know this is right way to do it. But why do we have to retain it after we get it from another object, does not this mean returning object has retain count 0 ? so we have to reatin it to count 1 to use it? but if it has reatin count 0, how do we know it is still there. We can assume since it is the next line that increment retain count that the object memory wont be realocated, but what if we have multi-threading program?

Upvotes: 1

Views: 75

Answers (2)

Nicolas Bachschmidt
Nicolas Bachschmidt

Reputation: 6505

The method getFoo doesn't return an object with a 0 retain count. It returns an object with a +0 retain count which means that:

  • the object's retain count is not null (otherwise, the object wouldn't exist)
  • and the retain count wasn't altered by the invocation of the method, or if it was, it was in a balanced way (with as many release/autorelease as retain/alloc/new/copy).

Thus the lifetime of the object entirely depends on where and how it is retained. We don't know how long the object will be valid as any method invocation could release the object.

For example, let's consider the following code:

id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];

The object anObject isn't retained any more by the array as we removed it. Therefore it may have been destructed (but maybe it wasn't because it is still used somewhere else).

Generally, when getting an object from a method (other that alloc, copy, new or retain), we can assume that:

  • either the object was retained then autoreleased,
  • either the object is retained by the object that returned it.

So we know the object foo is valid until we return from the current method/function or we invoke a method/function that alter the state of the object bar, whichever comes first. After that, it may have been destructed.

So in your case, you can safely omit the retain/release pair.

However, it is very difficult to guaranty that an object doesn't get released unless we know the implementation of every method we invoke. Therefore, retaining (then releasing) every single object we get is the safer approach and that's what the compiler will do when you enable ARC (Automatic Reference Counting).

But that would require you to write a lot of retain/release and your code would become difficult to read, understand and maintain. Moreover, the more code you write, the more bugs you get (unless you never write bugs).

In conclusion, you don't need to retain an object unless you have a reason to suspect it could vanish otherwise.

Upvotes: 0

trojanfoe
trojanfoe

Reputation: 122391

When an class method returns an object, it will autorelease it so you don't have to bother; typically:

- (Foo *)getFoo
{
    return [[_foo retain] autorelease];
}

If you are only using foo for the lifetime of the calling method you don't need to retain it, as it won't be autoreleased until next time through the run loop, so your code should actually be:

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];

If, however, you want to hold foo for a while, outside the scope of the calling method, you need to retain it and then release it sometime later.

One more thing; the convention for getter method names is simply "name", so your setter should be setFoo and your getter would be foo. Keeping to the naming conventions is a good idea as it lets you know what a method does, in say 7 months time, and tools like static analysis understand the conventions.

Upvotes: 3

Related Questions