When I use assign when declaring a synthesized propery, does ARC automatically still create a matching ivar to it? My property is as follows
#property (nonatomic, assign) NSString *text:
And
- (NSString *)text {
return self.label.text; // label is a UILabel
}
- (void)setText:(NSString *)text {
self.label.text = text;
}
I never have any use for the automatically generated _text ivar; does the compiler still create this ivar when I omit #synthesize text = _text or does the unused ivar just persist in the memory unused?
Do not use assign this way. It probably won't matter in this particular case, but it's extremely confusing to the caller, and it'll generate very bad bugs if you ever change the implementation.
The fact that you implemented the getter and setter means that the compiler won't generate an ivar. That has nothing to do with what memory-management attribute you use. Use strong here because that's what you implemented. Your header should match your implementation.
The ivar is created automatically for you only if you haven't implemented your property yourself.
And the #synthesize text = _text; is done automatically unless you provide your own implementation for getter and setter or synthesize the property to some other variable. For example:
#synthesize text;
The above will synthesize text property to text variable.
As for using assign instead of copy, that will theoretically use less memory, but is dangerous at the same time. If you use mutable strings, if you change the string value after assigning it to a property, the property value will also change, which is not what you want in most cases.
Are you worried about 4-8(32/64 bit pointers) bytes of extra allocations per instance? Using assign, weak or strong strong will not change the memory footprint. No matter what you use the string is not copied the reference always points to the same instance. The difference is only that the assig, weak do not increase the ref count of the object so by omitting the ivar you only "save" 4-8 bytes depending on what architecture you use.
Related
Should I have to manually copy object in custom setter with copy property in objective-c?
For example,
I have a property:
#property (copy, nonatomic) NSString *someString;
and custom setter:
- (void)setSomeString:(NSString *)someString
{
//option 1
_someString = someString;
//option 2
_someString = [someString copy];
//do other stuff
}
Is it option 1 enough for custom setter or I have to use option 2 instead in order to have copied object?
You can do whatever you like but you should use the second option.
This is because it will be something like code documentation if other developer see it he or she will know that you copy the string just by looking at:
#property (copy, nonatomic) NSString *someString;
The same if you use retain/assign it's best practice to retain/assign object in custom setter. It will make your code more clearer more documented and much more understandable for others developers.
You Must use "option 2" because you are using "copy" for your property and statement :
_someString = [someString copy];
would create a new object in memory and assign it to your property object.
If you write your own custom setter, then you are 100% responsible for everything it does. In your case, you are 100% responsible for the bug that you introduce with option 1 of your code: If I set someObject.someString to a mutable string and change the string later, then the string in your object will change which is most definitely not what you expect from a copy property.
In addition, if you have both a custom setter and getter (or a custom getter for a read-only property) so there is no compiler generated getter or setter, the compiler doesn't create the instance variable for you; you'll have to do that yourself.
You should also notice that "copy" of immutable objects doesn't actually copy them but just retains them, so usually the "copy" operation is really cheap, and when I pass a mutable object, "copy" was most likely what you wanted anyway.
Go with option 2 if you want to make own setter but don't forget to add the condition before the statement like...
if(_someString) {
[_someString release];
}
Note:- In case of ARC use statement "_someString = nil" instead
of "[_someString release]";
#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.
This is a two part question in hopes that I can understand more about the topic.
1) It seems to me that you have two popular options for declaring a property for a class in objective c. One is to add the property to the header's class body eg.
#interface MyClass : NSObject {
NSArray *myArray;
}
Or you can add it after the #interface body and before the #end statement like so.
#interface MyClass : NSObject {
//
}
#property (nonatomic, retain) NSArray *myArray;
What is the difference between these two "styles" and when do you choose one over the other?
2) after the #property you find options such as (nonatomic, retain). What are those for and why/when do you use different options?
Here are the only property modifiers that Xcode recognizes:
nonatomic (does not enforce thread safety on the property, mainly for use when only one thread shall be used throughout a program)
atomic (enforces thread safety on the property, mainly for use when multiple threads shall be used throughout a program) (default)
retain / strong (automatically retains / releases values on set, makes sure values do not deallocate unexpectedly) (default if ARC and object type)
readonly (cannot set property)
readwrite (can both set and get property) (default)
assign / unsafe_unretained (no memory management shall be done with this property, it is handled manually by the person assigning the value) (default if not ARC or object type)
copy (copies the object before setting it, in cases where the value set must not change due to external factors (strings, arrays, etc).
weak (automatically zeroes the reference should the object be deallocated, and does not retain the value passed in)
getter=method (sets the selector used for getting the value of this property)
setter= method (set the selector used for setting the value of this property)
1) #property is a special way to define getter- and setter-methods, or as we call them accessors in Objective-C. Your first snippet just declares an array for which you have to declare and write accessors yourself. For example setMyArray: and myArray.
Using #property will declare your accessors for you and is equivalent to declaring setMyArray: and myArray yourself. It is the preferred way to declare accessors since Objective-C 2.0. Note that you still have to declare the property (in your case myArray) yourself.
2) You first need to know about #synthesize. Remember that #property DECLARES the accessors for your property, #synthesize will IMPLEMENT them. When you use an #property in your #interface you mostly likely write an #synthesize in #implementation. Using #synthesize is equivalent to implementing setMyArray: and myArray.
The attributes (nonatomic, retain) tell the compiler, among others, how the memory management should work and therefore how the methods will be implemented. Note that you never actually see these accessors, but be assured that they are there and ready for you to be used.
To read more on that topic I recommend reading Section 9 on Properties from the following Tutorial or buy a Book that covers an Introduction to Objective-C.
Also you should familiarize yourself with at least the following attributes:
Access
Choose readwrite (default) or readonly. If readonly is set, ONLY the getter methods will be available.
Setter Memory Management
assign (default), simply assigns the new value. You mostly likely only use this with primitive data types.
retain, releases the old value and retains the new. If you use the garbage collector, retain is equivalent to assign. Why? The manual release of the old value will be done by the garbage collector.
copy will copy the new value and release the old value. This is often used with strings.
Threading
atomic (default) will ensure that the setter method is atomic. This means only one thread can access the setter at once.
nonatomic, use this when you don't work with threads.
This post gives you a good introduction to memory management and assign, retain and copy.
Properties are basically the accessor methods. They define the scope of the variable.
First case as given above,the variable is not accessible in other classes whereas by declaring a property as in the second case,variable is accessible in other classes also.
Also, they are useful for memory management.
First one will be private declaration and will not be accessible by other classes if you do not define the second one. Second is used together with #synthesize in .m module , and setter/getter's are created for you by the compiler. You can still define your own getter or setter with this. In this case all iVars defined in #property can be accessed by other classes.Retain/release operations are done automatically.
You should read Apple documentation for more details.
please check:
What's the difference between the atomic and nonatomic attributes?
Properties are basically the accessor methods. They define the scope of the variable. by default access specifior of variable is protected and properties set its Specifier from protected to Public
When using ARC for iOS, is there any difference between the following?
#property (strong, nonatomic) NSObject *someProperty;
...
#synthesize someProperty;
//and then in the init method, either:
self.someProperty = aProperty;
//or
someProperty = aProperty;
I know that without ARC, self.someProperty is actually calling the synthesized setter method which sends a retain message to the object. But now with ARC, does it matter if I use dot notation for setting a property like this?
More generally, does ARC truly mean that I don't have to worry about reference counts at all? Or are there certain situations in which the way I wrote my code could cause ARC to make a mistake?
The difference is the same as in the case without ARC: by using dot notation, you are calling the synthesized setter, and by assigning directly to the ivar, you are going around the setter method.
Under ARC, there are no differences in memory management between the two options but you should still make a conscious decision between the two options: assigning directly to the ivar bypasses KVO, for example, while going through the setter method is slightly slower but probably safer in most cases, e.g. when you later decide to make the property atomic or override the setter.
Personally, I would always use the property notation self.abc = ...; except possibly in init where it is often desirable to bypass KVO. In short, use the same reasoning you used before ARC.
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.