What does retain as property attribute exactly do in objective-c? - ios

If I declare a public property as :
#property (retain) NSString * name;
Then how does the compiler implicitly implement this? I have read that the retain gains ownership over the instance variable "_name". I have also read that "retain" message increases the reference count of the object.
So each time I call the setter for "name" property in the above example, will it increase the reference count?
So after this,
object.name=#"name1";
object.name=#"name2";
Will the reference count be 2?

To answer your specific question:
object.name = #"name1";
name now holds a strong reference to the "name1" string instance.
object.name = #"name2";
name now holds a strong reference to the "name2" string instance. No object holds a reference to the "name1" instance, and a release statement will be inserted by the compiler for "name1". (in practice, the first statement will likely be optimized away entirely).

According to Blamdarot in this answer:
"retain" is needed when the attribute is a pointer to an object. The setter generated by #synthesize will retain (aka add a retain count) the object. You will need to release the object when you are finished with it.

Related

iOS copy properties creation of new objects, retain, memory allocation

If I have a copy property and set it to another object, I actually create a new object with a retain count of 1.
#property (copy) myObject;
myobject = someOtherObject;
//&myOBject != &someOtherObject
At this point, let's call address of myObject &myObject1.
If I go and do this after I set myObject to someOtherObject
myObject = someOtherObject2
what happens to &myObject1? Now myObject point to a value that is equivalent to someOtherObject2's value but at a new memory address. What happens to the &myObject1 and is there anything still pointing to it?
Note that the #property statement in the question does not have a type supplied.
If someOtherObject is immutable a copy is not made, only the reference count in incremented and both myobject and someOtherObject point to the same object. That os all that is needed since an immutable object can not be changed. A change to either pointer will change the single object.
If someOtherObject is mutable a copy is made and there are now two distinct instances. No change is made to the original someOtherObject. Both my object and someOtherObject point to separate instances and have no relation to each other. If they are mutable a change to one will not change the other.

What happens when a object is assigned to another object?

For example:
myVC.bunnies = self.myBunnies;
or
[self getBunniesWithCompletion:^(NSArray *bunnies) {
self.myBunnies = bunnies;
}];
Is the object copied, or it's just its reference that is copied, and if it gets destroyed everything will break?
The property is declared like so:
#property (strong, nonatomic) NSArray *myBunnies;
When you do this assignment, a reference is copied, and a reference count is incremented. All of this is done implicitly through ARC, because you declared your property strong.
If you would like a copy to be made, change the declaration to
#property (copy, nonatomic) NSArray *myBunnies
This would be more expensive, but the array inside your object would be insulated from the array passed into the setter.
It totally depends on the way you declared the property:
#property(strong) : the object reference count is increased, meaning that the object self keeps a reference to the affected object so that this object is not released (until the reference has been released by setting it to nil)
#propery(weak) : the object reference is simply assigned but the reference count is not increased, meaning that self does not retain a reference to it
#property(copy) : the object is copied (using <NSCopying>'s copy method) and thus a new instance is stored, independant from the first one
I strongly recommand you to read the Advanced Memory Managment Programming Guide in the Apple Doc. It is not totally up-to-date as some parts of the doc still describe the way it works before ARC was the standard, but it's still always interesting to read to understand those mecanisms.

Whether I should use #property(nonatomic,copy) or #property(nonatomic,strong) for my (NSString *) attr in An object?

#interface PaneBean : NSObject
#property(nonatomic,copy) NSString *name;
#property(nonatomic,copy) NSString *type;
#property(nonatomic,assign) NSInteger width;
#end
I have a PaneBean as is shown above.
Whether I should use #property(nonatomic,copy) or #property(nonatomic,strong) for my (NSString *) name? What is the difference between them?
And is it right to write 'assign' for NSInteger?
Any help appreciated.Thanks in advance!
'copy' will cause the setter for that property to create a copy of the object, and is otherwise identical to strong. You would use this to make sure that if someone sets your property to a mutable string, then mutates the string, you still have the original value. If the string isn't mutable, Cocoa will silently optimize out the copy operation, which is nice :)
'strong' will keep the property's value alive until it's set to something else. If you want incoming mutable strings to change out from under you (not impossible, but not all that common, a thing to want), then strong would be the right thing to do. Generally strong is more useful for objects that represent something more complex than a simple "value" (i.e. not NSString, NSNumber, NSValue, etc...).
'assign' is the default (and indeed only) possible setting for an integer. Integers can't be retained or copied like objects.
For attributes whose type is an immutable value class that conforms to the NSCopying protocol, you almost always should specify copy in your #property declaration. Specifying retain is something you almost never want in such a situation.In non ARC strong will work like retain
Here's why you want to do that:
NSMutableString *someName = [NSMutableString stringWithString:#"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:#"Debajit"];
The current value of the Person.name property will be different depending on whether the property is declared retain or copy — it will be #"Debajit" if the property is marked retain, but #"Chris" if the property is marked copy.
Since in almost all cases you want to prevent mutating an object's attributes behind its back, you should mark the properties representing them copy. (And if you write the setter yourself instead of using #synthesize you should remember to actually use copy instead of retain in it.)
copy sends the copy message the object you set, while strong only retains it (increments the reference count).
For NSString , or in general any inmutable class with known mutable subclasses(NSArray, NSDictionaty, NSSet), copy is preffered to avoid clients setting a mutable instance and modifying it out of the object.
For primitive types(int for example) copy/strong does not make sense and by default assign is used. Is up to you if you want to put it explicitly or not.
Strong indicates composition, while Weak indicates aggregation.
Copy means that a new object is to be created before the contents of the old object are copied into the new object. The owning object, PaneBean in this case, will be composed of the newly created object.

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.

Objective-C 101 (retain vs assign) NSString

A 101 question
Let's say i'm making database of cars
and each car object is defined as:
#import <UIKit/UIKit.h>
#interface Car:NSObject{
NSString *name;
}
#property(nonatomic, retain) NSString *name;
Why is it #property(nonatomic, retain) NSString *name; and not #property(nonatomic, assign) NSString *name;?
I understand that assign will not increment the reference counter as retain will do. But why use retain, since name is a member of the todo object the scope of it is to itself.
No other external function will modify it either.
There's no such thing as the "scope of an object" in Objective-C. Scope rules have nothing to do with an object's lifetime — the retain count is everything.
You usually need to claim ownership of your instance variables. See the Objective-C memory management rules. With a retain property, your property setter claims ownership of the new value and relinquishes ownership of the old one. With an assign property, the surrounding code has to do this, which is just as mess in terms of responsibilities and separation of concerns. The reason you would use an assign property is in a case where you can't retain the value (such as non-object types like BOOL or NSRect) or when retaining it would cause unwanted side effects.
Incidentally, in the case of an NSString, the correct kind of property is usually copy. That way it can't change out from under you if somebody passes in an NSMutableString (which is valid — it is a kind of NSString).
and don't forget to access it via
self.name = something;
because
name = something;
will not care about the generated setter/getter methods but instead assign the value directly.
Without retain there is no guarantee the NSString* you are setting name with will live any longer than the assignment statement itself. By using the retain property for the synthesized setter you're allowing it to tell the memory management system that there is at least one more object interested in keeping the NSString* around.
For those who are looking for it, Apple's documentation on property attributes is here.
The self. in:
self.name = something;
is important! Without it, you are accessing the variable directly and bypassing the setter.
The older style (correct me if I am wrong) would have been:
[self setName:something];
Anyway, this notation was the (vaguely familiar sounding) advice that I really needed when I went looking for proper #properties on NSStrings. Thanks Axel.
After reading so many Articles, SO posts and made demo apps to check Variable property attributes, I decided to put all the attributes information together
atomic //default
nonatomic
strong=retain //default
weak= unsafe_unretained
retain
assign //default
unsafe_unretained
copy
readonly
readwrite //default
so below is the detailed article link where you can find above mentioned all attributes, that will defiantly help you.
Many thanks to all the people who give best answers here!!
Variable property attributes or Modifiers in iOS
retain = strong
it is retained, old value is released and it is assigned
retain specifies the new value should be sent -retain on assignment and the old value sent -release
retain is the same as strong.
apple says if you write retain it will auto converted/work like strong only.
methods like "alloc" include an implicit "retain"
Example:
#property (nonatomic, retain) NSString *name;
#synthesize name;
assign
assign is the default and simply performs a variable assignment
assign is a property attribute that tells the compiler how to synthesize the property's setter implementation
I would use assign for C primitive properties and weak for weak references to Objective-C objects.
Example:
#property (nonatomic, assign) NSString *address;
#synthesize address;
Google's Objective-C Style Guide covers this pretty well:
Setters taking an NSString, should always copy the string it accepts.
Never just retain the string. This avoids the caller changing it under you without your knowledge. Don't assume that because you're accepting an NSString that it's not actually an NSMutableString.
Would it be unfortunate if your class got this string object and it then disappeared out from under it? You know, like the second time your class mentions that object, it's been dealloc'ed by another object?
That's why you want to use the retain setter semantics.

Resources