Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it okay for multiple objects to retain the same object in Objective-C/Cocoa?

Say I have a tableview class that lists 100 Foo objects. It has:

@property (nonatomic, retain) NSMutableArray* fooList;

and I fill it up with Foos like:

self.fooList = [NSMutableArray array];
while (something) {
  Foo* foo = [[Foo alloc] init];
  [fooList addObject:foo];
  [foo release];
}

First question: because the NSMutableArray is marked as retain, that means all the objects inside it are retained too? Am I correctly adding the foo and releasing the local copy after it's been added to the array? Or am I missing a retain call?

Then if the user selects one specific row in the table and I want to display a detail Foo view I call:

FooView* localView = [[FooView alloc] initWithFoo:[self.fooList objectAtIndex:indexPath.row]];  
[self.navigationController pushViewController:localView animated:YES];
[localView release];

Now the FooView class has:

@property (nonatomic, retain) Foo* theFoo;

so now BOTH the array is holding on to that Foo as well as the FooView. But that seems okay right? When the user hits the back button dealloc will be called on FooView and [theFoo release] will be called. Then another back button is hit and dealloc is called on the tableview class and [fooList release] is called.

You might argue that the FooView class should have:

@property (nonatomic, assign) Foo* theFoo;

vs. retain. But sometimes the FooView class is called with a Foo that's not also in an array. So I wanted to make sure it was okay to have two objects holding on to the same other object.

like image 852
Andrew Arrow Avatar asked Apr 26 '10 17:04

Andrew Arrow


3 Answers

To answer your main question, yes you can multiple objects retaining an instance. That is exactly the point of reference-counted memory management. Have a look at the Cocoa Memory Management Programming Guide for more info. Then re-read it. It has all of the answers and will be your best friend.

Basically, sending a -retain message indicates that the sender "owns" the receiver in the sense that the receiver should not be deallocated until all owners have released their ownership. Thus, individual instances don't need to know (nor should they care) whether other owners exist. Retain anything you need to keep around and release it when you're done with it. When all owners have released their ownership, an intsance can be deallocated.

On a side note,

@property (retain,readwrite) NSMutableArray *myArray;

declares that the class declaring this property will retain the NSMutableArray instance. NSArray, NSDictionary, and NSSet (and their mutable subclasses) always retain their contents.

like image 119
Barry Wark Avatar answered Nov 18 '22 08:11

Barry Wark


As others say, what you are doing is correct, and the code looks correct to me. I have tens of references to the same object in my code and as long as I have balanced all the retains and releases, everything works fine.

To add a bit more detail... you ask:

because the NSMutableArray is marked as retain, that means all the objects inside it are retained too?

These are two different things. All collection classes (Dictionaries, Arrays, Sets) automatically retain things that you add to them, and release their content objects when the collection object is deallocated. (In case of NSMutableArray, the content object gets released either if you remove it individually from array, or when you deallocate the whole array.)

This has nothing to do with whether the collection object itself is retained or assigned as a property. The only thing to consider there is that if your policy for the collection object property is not correct, it might get released sooner or later than you think and things may get out of balance.

As others say... read the memory management guide, and practice. :) Oh, and read other people's code too from this perspective and try to understand how/why they are doing their memory management.

One other small thing... for every retained property, make sure you have a release call in the object's dealloc method.

like image 37
Jaanus Avatar answered Nov 18 '22 07:11

Jaanus


Yes, it's ok. That's the entire point of a reference counting memory management system.

like image 4
Carl Norum Avatar answered Nov 18 '22 06:11

Carl Norum