1

I have search many links and read many articles but I can not found exact difference of retain and assign..

I am trying the following:

NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3", nil];
NSMutableArray *arr2=[arr1 retain];
NSMutableArray *arr3 = arr1; //Assign

[arr1 addObject:@"66"];

NSLog(@"Array one   : %@",arr1);
NSLog(@"Array two   : %@",arr2);
NSLog(@"Array three : %@",arr3);

Output :

Array one   : (
    1,
    2,
    3,
    66 
)  

Array two   : (
        1,
        2,
        3,
        66
)  

Array three : (
        1,
        2,
        3,
        66 
)

Above example give me the same output.

Considering the above example, how can i define difference between assign and retain?

If above example is wrong than please give provide answer with better examples.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Ravi Pathak
  • 83
  • 1
  • 8
  • retain shouldn't be used any more. Use ARC, but to answer your question (and assuming you aren't using ARC) see what happens to arr3 if you do `[arr2 release]` – Paulw11 Aug 15 '16 at 12:15

3 Answers3

6

You are looking at three different variables pointing to the same object, so of course when you display the output, you'll see the same object each time.

The retain vs assign are types of memory qualifiers, but don't affect what the the underlying object is. Specifically, they merely affect the retainCount of the underlying object.

Let's look at your three lines of code:

NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3", nil];

That creates an object with a retain count of +1.

NSMutableArray *arr2 = [arr1 retain];

This increases the retain count of that object to +2, and you have another variable that points at that same object.

NSMutableArray *arr3 = arr1; //Assign

This doesn't increase the retain count any further, and you now have a third variable that points to the same object.


The fundamental game of "reference counting" memory management is to ensure that:

  • an object that is being used has a positive retain count (so that it isn't deallocated while you are still using it) ... failure to do this properly can result in an object being deallocated prematurely, possibly leaving you with dangling references; and

  • an object with which you have no further use has its retainCount reduced to zero, so that when the autorelease pool is drained, the object will be deallocated ... failure to decrement the counter at the right places can result in an object being leaked.

As you can imagine, this results in a fairly fragile process, where we must make sure that we increment and decrement our retain counts with retain, release and autorelease in the right places. Xcode's "static analyzer" ("Analyzer" option on Xcode's "Product" menu or by pressing shift+command+B) does an excellent job of looking at our code and identifying whether we've done this properly. If you're writing manual reference counting code, this tool is indispensable.

But, the beauty of "automatic reference counting" is that we leave this silly world of incrementing and decrementing the object retainCount values behind us. We shift to a world where we can focus on the "object graph", what sorts of references we need at certain places in our code, and the compiler takes care of incrementing and decrementing the retainCount for us.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
3

All 3 references are pointing to the same instance.

NSMutableArray *arr2=[arr1 retain]; .
increases the reference count and returns a pointer to the same instance (i.e. self).

NSMutableArray *arr3 = arr1;
assigns the arr1 reference directly, without passing it through any method calls.

The only difference is that you have increased the reference count in one case, and you haven't in other.
The mechanics of assigning the reference is the same. It doesn't matter if the reference is direct (arr3 = arr1), or indirect, through calling a method on arr1 that returns a reference to itself.

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Avi
  • 7,469
  • 2
  • 21
  • 22
3

assign and retain are 2 strategies related to memory management in objective-C.

Please see: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

Anyway calling retain on an object doesn't change it's value, so it is normal that you would get the same output.

retain / release where introduced and popularized in objective-C at the early stage of iOS, when apple forbad the use of Garbage collector for ios developpement due to performance concerns. Due to the lack of Garbage collector, developers had to manually deal with object destruction when they weren't needed anymore. Thus being quite a challenge, retain / release was then a way of helping the developers with a better handling of this problem.

Beginning in iOS 5 Apple introduced ARC (automatic reference counting) which has to be used for any new developement, especially if you are not familiar with Memory management. ARC allow developers to stop managing object lifecycle with retain / release as the memory managemet code (ie the [object retain] and [object release]) are added during the compile process. The developer has then only to care about memory management when declaring properties:

@property(assign) int value;
@property(strong) id object;
@property (weak) id object;

In this context strong and retain are similar and can be exchanged. strong and weak being just new words to make it easier for beginners to understand what was going on behind the hood. Also assign is assume par default and is then not necessary.

A property marked as strong will receive a retain call during the setObject: will a property marked weak won't. Since retain is only for object (instanciated in the Heap), basic C type property (bool, int, float, struct...), since they are instanciate in the Stack, should be mark assign.

If you see retain in a piece of code, it's just that this class is not using ARC and it's just memory management code.

Florian Burel
  • 3,408
  • 1
  • 19
  • 20