Objective C - Assign, Copy, Retain - ios

I'm new to Objective C. I have basic knowledge in C, including the concept of pointers. I have two basic questions:
Can someone explain the difference between assign,copy, and retain with some analogy?
How do you handle a function which returns pointer variable, and how do you perform messaging through a return pointer?

Updated Answer for Changed Documentation
The information is now spread across several guides in the documentation. Here's a list of required reading:
Cocoa Core Competencies: Declared property
Programming with Objective-C: Encapsulating Data
Transitioning to ARC Release Notes
Advanced Memory Management Programming Guide
Objective-C Runtime Programming Guide: Declared Properties
The answer to this question now depends entirely on whether you're using an ARC-managed application (the modern default for new projects) or forcing manual memory management.
Assign vs. Weak - Use assign to set a property's pointer to the address of the object without retaining it or otherwise curating it; use weak to have the property point to nil automatically if the object assigned to it is deallocated. In most cases you'll want to use weak so you're not trying to access a deallocated object (illegal access of a memory address - "EXC_BAD_ACCESS") if you don't perform proper cleanup.
Retain vs. Copy - Declared properties use retain by default (so you can simply omit it altogether) and will manage the object's reference count automatically whether another object is assigned to the property or it's set to nil; Use copy to automatically send the newly-assigned object a -copy message (which will create a copy of the passed object and assign that copy to the property instead - useful (even required) in some situations where the assigned object might be modified after being set as a property of some other object (which would mean that modification/mutation would apply to the property as well).

The Memory Management Programming Guide from the iOS Reference Library has basics of assign, copy, and retain with analogies and examples.
copy
Makes a copy of an object, and returns it with retain count of 1.
If you copy an object, you own the copy. This applies to any method that contains the word copy where “copy” refers to the object being returned.
retain Increases the retain count of an object by 1. Takes ownership of
an object.
release Decreases the retain count of an object by 1. Relinquishes
ownership of an object.

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"First",#"Second", nil];
NSMutableArray *copiedArray = [array mutableCopy];
NSMutableArray *retainedArray = [array retain];
[retainedArray addObject:#"Retained Third"];
[copiedArray addObject:#"Copied Third"];
NSLog(#"array = %#",array);
NSLog(#"Retained Array = %#",retainedArray);
NSLog(#"Copied Array = %#",copiedArray);
array = (
First,
Second,
"Retained Third"
)
Retained Array = (
First,
Second,
"Retained Third"
)
Copied Array = (
First,
Second,
"Copied Third"
)

assign
assign is a default property attribute
assign is a property attribute tells the compiler how to synthesize the property’s setter implementation
copy:
copy is required when the object is mutable
copy returns an object which you must explicitly release (e.g., in dealloc) in non-garbage collected environments
you need to release the object when finished with it because you are retaining the copy
retain:
specifies the new value should be sent “-retain” on assignment and the old value sent “-release”
if you write retain it will auto work like strong
Methods like “alloc” include an implicit “retain”

Related

use __weak to local variable in ARC

When you write code like below in ARC
__weak NSMutableArray* array = [[NSMutableArray alloc] init];
The compiler will show you a warning or error and say "Assigning retained object to weak variable. object will be released after assignment".
But if you write like this:
__weak NSMutableArray* array = [NSMutableArray array];
There is no error.
I'm wondering if the second usage is reasonable in some situations? What's the difference between these two codes from memory management perspective? How does it work?
There can be very subtle differences that the compiler cannot know.
Let's take an immutable version: [NSArray array] could return the very same static object every time. So your weak variable will point to a valid object, that has a strong reference somewhere else. Or think of the singleton pattern. On the other hand, when calling alloc/init, convention dictates that you're the only owner of that object, and that will typically leave you with nothing.
Also, the factory method certainly looks more like a (functional) method. In any case, it doesn't communicate ownership of what it returns very well. For an autoreleased object, it's not clear whether you're the the only owner or a shared owner.
They are the same because you lose the object instantly. Compiler cannot know probably, except alloc init, that the object will be lost.
In the first form, the method returns a retained object. ARC ensures, that the object is released when there is no strong reference on the call-site. This is immediately true, with the weak reference - thus, the compiler emits a warning or error.
In the second form, the method returns an unretained object. In this case, the compiler must ensure that the object is still valid across the return boundary. When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. That is, there is a strong reference created by the compiler. This strong reference will be automatically released by the compiler generated code.
Thus, in this case there's no error or warning.
In the worst case, holding that object may require to use an autorelease pool. However the compiler can apply certain optimisations which avoids this. Thus we should not assume that the returned object lives in an auto release pool.
See specification: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14
See also this question on SO: Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]

How to know which attributes to use with different properties? [duplicate]

Can someone explain to me in detail when I must use each attribute: nonatomic, copy, strong, weak, and so on, for a declared property, and explain what each does? Some sort of example would be great also. I am using ARC.
Nonatomic
Nonatomic will not generate threadsafe routines thru #synthesize accessors. atomic will generate threadsafe accessors so atomic variables are threadsafe (can be accessed from multiple threads without botching of data)
Copy
copy is required when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
Assign
Assign is somewhat the opposite to copy. When calling the getter of an assign property, it returns a reference to the actual data. Typically you use this attribute when you have a property of primitive type (float, int, BOOL...)
Retain
retain is required when the attribute is a pointer to a reference counted object that was allocated on the heap. Allocation should look something like:
NSObject* obj = [[NSObject alloc] init]; // ref counted var
The setter generated by #synthesize will add a reference count to the object when it is copied so the underlying object is not autodestroyed if the original copy goes out of scope.
You will need to release the object when you are finished with it. #propertys using retain will increase the reference count and occupy memory in the autorelease pool.
Strong
strong is a replacement for the retain attribute, as part of Objective-C Automated Reference Counting (ARC). In non-ARC code it's just a synonym for retain.
This is a good website to learn about strong and weak for iOS 5.
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1
Weak
weak is similar to strong except that it won't increase the reference count by 1. It does not become an owner of that object but just holds a reference to it. If the object's reference count drops to 0, even though you may still be pointing to it here, it will be deallocated from memory.
The above link contain both Good information regarding Weak and Strong.
nonatomic property means #synthesized methods are not going to be generated threadsafe -- but this is much faster than the atomic property since extra checks are eliminated.
strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
weak ownership means that you don't own it and it just keeps track of the object till the object it was assigned to stays , as soon as the second object is released it loses is value. For eg. obj.a=objectB; is used and a has weak property , than its value will only be valid till objectB remains in memory.
copy property is very well explained here
strong,weak,retain,copy,assign are mutually exclusive so you can't use them on one single object... read the "Declared Properties " section
hoping this helps you out a bit...
This link has the break down
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property
assign implies __unsafe_unretained ownership.
copy implies __strong ownership, as well as the usual behavior of copy
semantics on the setter.
retain implies __strong ownership.
strong implies __strong ownership.
unsafe_unretained implies __unsafe_unretained ownership.
weak implies __weak ownership.
Great answers!
One thing that I would like to clarify deeper is nonatomic/atomic.
The user should understand that this property - "atomicity" spreads only on the attribute's reference and not on it's contents.
I.e. atomic will guarantee the user atomicity for reading/setting the pointer and only the pointer to the attribute.
For example:
#interface MyClass: NSObject
#property (atomic, strong) NSDictionary *dict;
...
In this case it is guaranteed that the pointer to the dict will be read/set in the atomic manner by different threads.
BUT the dict itself (the dictionary dict pointing to) is still thread unsafe, i.e. all read/add operations to the dictionary are still thread unsafe.
If you need thread safe collection you either have bad architecture (more often) OR real requirement (more rare).
If it is "real requirement" - you should either find good&tested thread safe collection component OR be prepared for trials and tribulations writing your own one.
It latter case look at "lock-free", "wait-free" paradigms. Looks like rocket-science at a first glance, but could help you achieving fantastic performance in comparison to "usual locking".

What is the role of the "copy" in the ARC

What is the role of keyword copy in the ARC
I find the copy(keyword) can be used in ARC while retain and release cannot be used. Moreover is the role of copy in ARC is the same as the role of copy in MRC? If yes , does copy make the retainCount +1 in ARC?
And I have seen mike ash blog about ARChe said :
you need to explicitly copy blocks that you pass as id parameters:  
[myArray addObject: [^{ DoSomethingMagical(); } copy]];
but when I test code like this (without using copy) it works well too.
NSArray *array = [[NSArray alloc] initWithObjects:^{NSLog(#"hahaha");}, nil];
[self test:[array objectAtIndex:0]];
- (void)test:(void (^)(void))completion
{
  completion();
}
Does it mean that there is no need to copy block when it used as an id type?
Yes , the role of copy in ARC is the same as the role of copy in MRR
The copy will invoke the copyWithZone: method . when it send to the mutable object , it will return a clone immutable object , which retainCount is 1. When it send to the immutable object , it will not copy , it will return the object itself , but the retainCount +1.
So when you use copy in ARC , you can use like this : object1 = [object2 copy]; ARC will manage the retainCount of the object1 , when then object1 is released by ARC , the object2's retainCount will be a corresponding change. So you do not worry about the memory.
About the block need be copy when pass as id parameters.
the apple document said :
Typically, you shouldn’t need to copy (or retain) a block. You only
need to make a copy when you expect the block to be used after
destruction of the scope within which it was declared. Copying moves a
block to the heap
and As ughoavgfhw said :
Blocks are similar to other objects for memory management, but not the
same. When a block which accesses local variables is created, it is
created on the stack. This means that it is only valid as long as its
scope exists. To save this block for later, you must copy it, which
copies it to the heap
Copy does just what the name implies. It returns a copy of the object. Say you have a mutable object and you have a pointer to it. You then reference it somewhere else in the code and ARC will assume you want to point at the same object and retain it for you. In this case if you modify either of them both will reflect the changes. If you point at it with a copy you will get a new object, and modifying one will not affect the other:
NSMutableArray* objA = [NSMutableArray new];
NSMutableArray* objB = objA;
/* adding an object to either will be in both since they point to the same object*/
objB = [objA mutableCopy];
/*adding an object to one WILL NOT affect the other, they are different, distinct objects*/
In the docs here:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1
It mentions that when blocks are copied all of their Objective-C Objects receive a strong reference so that they don't drop out of scope before the block is executed.
When you use copy in ARC, it does the same as without ARC, i.e. it creates a copy of the object that is receiving the copy (it creates a new object instance in memory), and creates a strong relationship to the object that executes the code.
This means that the copy of the object now has a retain count of 1, but this is of no relevance for you in ARC, since this is handled automatically.

iOS: Copy property

I couldn't get the right answer for this question. If it is found duplicate, please make it duplicate with the right reference link.
I wanted to know, what are the ways the reference count is incremented. I know, alloc/init and retain increases the reference count, does 'copy' also increases the reference count to '1' ?
Thanks.
copy creates a new object which is, as the method name suggest, a carbon copy of the receiver (well in fact it depends of the implementation of the copy method in each class, but that's the aim of the method anyway).
So in fact it does not really "increase the reference count of the by 1" but it rather create a new object, with a refcount of 1 as any newly allocated object, and make it have the same property / ivar values as the original.
So imagine you have a Person class with the properties name, surname and age, if you needed to implement the copy method yourself it would look sthg like this:
-(id)copy
{
// Create a new instance
Person* mycopy = [[Person alloc] init];
// Make it an exact copy of the original
mycopy.name = self.name;
mycopy.surname = self.surname;
mycopy.age = self.age;
// and return that copy
return mycopy;
}
Note that in this case, if you modify the copy later, the original is not modified, because it is a different instance.
With this principle, the original object does not have its refcount incremented by one, but you have a new object whose refcount is one (as if you just did alloc/init to create this new object yourself) and you still have to release or autorelease it at some point yourself (if you are not using ARC). That's why calling copy on an object obey the same rules as retain or alloc regarding the need to call release or autorelease to balance the refcount at some point
Note that there is some exceptions / special cases, especially for some classes that are known as "immutable", like NSArray or NSString. In such cases, it is reasonable to thingk that making a copy (aka a different object instance) that is a clone of the original, whereas the original cannot be modified, is not really efficient, and can be optimized.
So in cases like NSArray and NSString and some other, the copy method may simply implemented to do a simple retain as the behavior will be the same as you can't modify the original (and neither the copy) because these are immutable classes by nature.
Of course, the implementation of mutableCopy (to get an NSMutableArray from an NSArray for example) do a real copy and not a simple retain, and the implementation of the copy method in the mutable subclasses like NSMutableString and NSMutableArray do a real copy too, but for the case that request an immutable copy of an immutable object, the point of allocating a different instance is generally useless and memory-consuming and is thus implemented the same as a retain.
But all this probable optimization does not change neither the behavior (because the classes are immutable) nor the memory management policy (as you still need to release the object returned by copy)

iOS: Setting properties

When I'm setting a property with an object that is currently in a retained NSArray, will it only store the pointer (light-weight), or will it copy the contents to the property?
From what I know, it seems like it would only assign the pointer, but I'm not sure.
Also, under what circumstances would using *pointer = *otherPointer or the set methods (setDelegate, for instance) copy the value, instead of just passing the pointer, if any.
Shouldn't it always just pass the pointer address?
It always passes the pointer, as you said. Unless you are specifically adding a de-referencing sign, this will always be the case.
However, when you add a property to a class, and set the setter to copy:
#property (nonatomic, copy) id obj;
When using the dot syntax or the setter, This will be translated to:
_obj = [otherObj copy];
Here, it will depend whether the object in question supports copying itself, or will it fall back to it's super class NSObject or another intermediate class's copy.
Moreover, Collection classes NSDictionary and NSArray do a shallow copy, as in they copy the references to their objects only, so you have two collections pointing to the same set of objects.

Resources