I am so confused between self and underscore to access the property in Objective c, whenever we create property, its getter-setter automatically generated. So we can access the same property with self.property and same as _property. In my opinion, there shoulb be some difference which i am not getting. PLease tell me with examples.
The underbar (underscore) version is the actual instance variable, and should not be referenced directly. You should always go via the property name, which will ensure that any getter/setter actions are honoured.
So if you code _property = 4, you have directly set the variable. If you code self.property = 4, you are effectively making the method call [self setProperty:4], which will go via the setter (which might do something such as enforce property having a max value of 3, or updating the UI to reflect the new value, for example).
Edit: I though it was worth mentioning that the setter (setProperty) will issue a _property = 4 internally to actually set the instance variable.
when you are using the self.XX, you access the property via the setter or getter.
when you are using the _XX, you access the property directly skip the setter or getter.
Let's say you have a property defined as follows:
#property (nonatomic,strong) NSString* name;
The getters and setters of the name property are automatically generated for you.Now, the difference between using underscore and self is that:
self.name =#"someName"; // this uses a setter method generated for you.
_name = #"someName"; // this accesses the name property directly.
The same applies for getting the name property;
Related
I'm learning iOS development and choose to move back and forth between Objective-C and Swift to notice differences or similarities. While working through a tutorial in Objective-C, I noticed that Xcode autocomplete feature allows my code from the tutorial which reads:
taskField = [[UITextField alloc] initWithFrame:fieldFrame];
[taskField setBorderStyle:UITextBorderStyleRoundedRect];
[taskField setPlaceholder:#"Type a task, tap Insert"];
I decided to lookup UITextField reference pages, change the reference page's language to Objective-C, and noticed that the properties don't generally use the pre-text 'set'. Should the pre-text 'set' be used at all times for properties when writing in Objective-C?
Thank you in advance.
Short answer is that the following two lines are equivalent in this case:
taskField.borderStyle = UITextBorderStyleRoundedRect;
[taskField setBorderStyle:UITextBorderStyleRoundedRect];
set is the standard prefix on a "setter" method-- this can be a little confusing if you're new to ObjC. The actual property name here is e.g. borderStyle, and if you use the dot syntax setter, you would write taskField.borderStyle = .... If you invoke the setter with the message notation (brackets), then you use the setBorderStyle: explicitly.
Here's the history that explains this: Way back (10+ years ago anyway), ObjC did not have any declared, formal properties, and did not have "dot" syntax for accessing them. You'd create a "private" instance variable, and then you would write the idiomatic getters and setters for that value. By convention, the setter was prefixed with "set" and the getter had no prefix (it was just the "property name"). All access to that value, both get and set, was done with bracket notation. Fast forward through some intermediate evolution, and now the handy #property declaration will do a lot of automatic synthesis for you of all the once-cumbersome boilerplate code you used to have to write. The method synthesis naming rules are automatic and follow the earlier conventions. Most documentation today will demonstrate property access using dot notation, but the getter and setter methods are autogenerated, and are still available for direct use.
So in short, most often by convention, you will now write taskField.borderStyle = ..., but you can also call [taskField setBorderStyle:...]. The former essentially invokes the latter method, and both are semantically the same.
You access or set an object’s properties via accessor methods:
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:#"Johnny"];
By default, these accessor methods are synthesized automatically for you by the compiler, so you don’t need to do anything other than declare the property using #property in the class interface.
The synthesized methods follow specific naming conventions:
The method used to access the value (the getter method) has the same name as the property.
The getter method for a property called firstName will also be called firstName.
The method used to set the value (the setter method) starts with the word “set” and then uses the capitalized property name.
The setter method for a property called firstName will be called setFirstName:.
If you don’t want to allow a property to be changed via a setter method, you can add an attribute to a property declaration to specify that it should be readonly:
#property (readonly) NSString *fullName;
For details see this link Use Accessor Methods to Get or Set Property Values
This question already has answers here:
iOS: Usage of self and underscore(_) with variable [duplicate]
(3 answers)
Closed 8 years ago.
When I declare an NSString I simply do:
NSString * my_string; (in interface of my .h)
If I want to allow access to this string from other classes I add a property in this way
property (nonatomic, strong) NSString *my_string;
and I write the synthesize
synthesize my_string; (in .m)
Now I have some question about:
If I use a property, must I also use the simple declaration in interface?
If I use my_string as a property, must I always use self. before?
If I use a property, is it necessary to write #synthesize for each? (because I saw that sometimes it's not necessary.
If I use a property, must I also use the simple declaration in interface?
No, generally you just want to use the #property (it will quietly add an instance variable for you).
If I use my_string as a property, must I always use self. before?
You don't need to but you should. Using self. calls the accessor method to get the variable contents. Not using self. accesses the instance variable directly. So, if you add a custom accessor in the future you will need to refactor.
Often you will reuse the same variable multiple times. In this case, call self., but use it to set a local variable that you then use throughout the method (in this way the accessor is only called once).
If I use a property, is it necessary to write #synthesize for each? (because I saw that sometimes it's not necessary.
No, the compiler will add:
#synthesize propertyName = _propertyName;
for you, and that is a good approach to follow (separating the property name from the instance variable name).
NO
NO, using self. will execute accessor method, you can use it with name _my_string and then you'll access the variable directly. If you want a different variable name for your property then you must use synthetize with that name
NO, xcode will synthetize it automatically with the variable named _my_string
It's becoming more and more appropriate to use properties in all cases anymore. You can declare "private" properties inside a header extension inside the .m file if you don't want to expose them to outside classes. Say you have a property called name in the .h file:
#property (nonatomic, strong) NSString *name;
Users of this class can access the name property by saying theVariable.name, inside your .m file you need to access this property with self.name. However you can access the ivar like so:
_name = #"John Smith"
This will skip the property and go directly to the ivar. In this case if you had an overriden setter it won't be called.
You no longer need to synthesize properties. Xcode will automatically provide this:
#synthesize name = _name;
I try to write a custom setter method but I fail with the error message "Type of property 'pValue' does not match type of accessor 'setPValue:'". The array is passed successfully but I don't understand the the error message.
my .h-file:
#property (nonatomic, assign) double pValue;
- (double)getInverseCDFValue:(double)p;
- (void)setPValue:(NSArray*)aArray;
my implementation:
#synthesize pValue;
- (void)setPValue:(NSArray *)aArray {
double p = [[aArray objectAtIndex:22]doubleValue];
NSLog(#"p is: %f", p); //the value is written successfully
[self getInverseCDFValue:p]; //just calling another method for calculations
pValue = iCFDValue;
}
It works with passing single values but not with arrays. Is this not allowed in setter methods?
Thanks
When you synthesize your property, Xcode is going to generate setter and getter for your property unless your property is read-only. In this case, it's going to create only getter method for you. So, by naming convention, let's say you have a property name toto which type is double, your setter will be
-(void)setToto:(double d).
But what you can do is create another method set your property. But, you need to change your method name to something else. For example,
-(void)setTotoWithNSArray:(NSArray *).
You've defined a property pValue, which is of type double. Objective-C now expects that an accessor and a getter exist, with the names:
- (double)pValue; // Getter
- (void)setPValue:(double)value; // Setter
Either you let Objective-C autogenerate them for you, or you need to provide them explicitly.
Now you are providing a method with the same name, but a different type (NSArray). The type is different, and that's what the error message is telling you: the compiler thinks that the method is setter of your property, but you've given it the wrong type. It tells you because since you violate the expectations, the property cannot be used correctly in some contexts like Key-Value Coding. In almost all cases, what you've done is considered to be a bug.
You could make the pValue property read-only, I think that would make the warning disappear but it still would be bad because the type difference is confusing. Instead, rename the setter with the array argument to something else:
- (void)setPValueFromArray:(NSArray *)anArray;
This question already has answers here:
Is there a difference between an "instance variable" and a "property" in Objective-c?
(6 answers)
Closed 9 years ago.
What is the difference between these declarations, lets call them red and orange:
pros, cons?
The red set is properties, and the orange set is instance variables.
A property declaration tells the compiler to define a getter method, and possibly a setter method. (No setter method if the property is readonly.)
In newer versions of Objective C, declaring a property also creates an instance variable that is used to save values for the property. By convention the instance variable has the same name as the property, but with an "_" prefix. There is a way to change the name of the instance variable, but let's ignore that for now.
The property foo:
#property (nonatomic, strong) NSString *foo;
Would have a getter method:
- (NSString *) foo;
and a setter method
- (void) setFoo: (NSString *) foo;
That enables you to use code like this:
NSString *aString = self.foo;
or
NSString *aString = [self foo];
(2 different, equally valid ways of invoking the getter)
And invoking the setter
self.foo = #"a string";
or
[self setFoo: #"a string"];
(2 different, equally valid ways of invoking the setter)
Properties are really useful when you want to create a public interface to get and set values in your class from outside. If you declare a property as "atomic" the compiler adds additional code to the getter and the setter so reads and writes to the property are "thread safe", and can be accessed from background threads.
Before ARC, properties also were a very clean way to manage retains and releases. You declared a property as "retain" and the setter was written to retain the object that was passed in. That's less of an issue in ARC, because the system takes care of retains and releases for you.
It is also possible to write a custom getter or setter method that invokes your own code instead of the compiler-written code. You can use that to do things like log information, send notifications about changes, update labels, etc, etc. You simply add a method body to your .m file that has the same method signature as the getter or setter and the compiler uses that method instead of the automatically generated one.
As I said before, the code:
self.foo = #"a string";
is the same as
[self setFoo: #"a string"];
and invokes the setter method. The setter method sets the internal instance variable _foo.
However, the code
_foo = #"a string";
changes the instance variable directly, without invoking the setter. If you do define a property, you should use it instead of the instance variable.
Objective-c use to be simple...and tedious. You would declare instance variables for a class (the orange) and then you would define (usually) 2 methods for each, one so that an external class could set each instance variable to a new value, and one that returned the ivars value so an external object could read it. Aka, you had to write a getter and setter for each ivar. This was two lines of code in the interface and sometimes around 10 lines of code for the implementation file.
Then came properties, declared with #property. There was much rejoicing and drinking in the streets. These single #property lines told the compiler to write those methods for you, including the correct memory management code and even mutex locking code (depending on what you specified when declaring the #property)
Theres a whole lot of history, but nowadays, with automatic reference counting, it really only makes sense to use #properties in your interface, when you want to make an ivar public, and declare your private ivars in your implementation file.
Lastly, not that #property not only tells the compiler to implement your getter and setter, but it also automatically provides an instance variable with the same name, but prefixed with an underscore (this is only if you have implicit synthesizing of properies enabled...more history)
So, thats the difference. #property tells the compiler to write code for you (essentially). What code it actually writes is modified by all the different ways you can declare a #property.
I am reading Apple Doc for understanding property instance variable but bit confused
From Apple Doc:
Most Properties Are Backed by Instance Variables By default, a
readwrite property will be backed by an instance variable, which will
again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for
the life of the object. The memory used for instance variables is
allocated when the object is first created (through alloc), and freed
when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has
the same name as the property, but with an underscore prefix. For a
property called firstName, for example, the synthesized instance
variable will be called _firstName.
Although it’s best practice for an object to access its own properties
using accessor methods or dot syntax, it’s possible to access the
instance variable directly from any of the instance methods in a class
implementation. The underscore prefix makes it clear that you’re
accessing an instance variable rather than, for example, a local
variable:
If using accessor methods or dot syntax is best practice then why user _ivarPropertyName?
Why use ivar for presenting properties? what are its benefits? when apple says "using accessor methods or dot syntax is best practice"
#property declares the existence of a property (describing its interface), but doesn't specify the implementation of that property. But properties need to store their contents somewhere. By default, the compiler synthesizes an ivar for that (and matching setters and getters). So normally you can ignore the existence of the ivar and just use dot syntax.
I follow Apple's advice and try to avoid using ivars directly. But somtimes you want to access a property without invoking its getter. The most common exception in my code is lazily-initialized read-only properties:
#interface MyObject : NSObject
#property ( nonatomic, readonly ) id someProperty ;
#end
#implementation MyObject
#synthesize someProperty = _someProperty ; // required; compiler will not auto-synthesize ivars for readonly properties
-(id)someProperty
{
if ( !_someProperty )
{
_someProperty = ... create property here
}
return _someProperty ;
}
#end
Also, you may not want to invoke the getter for a property in your -dealloc method... for example, a timer property. To avoid creating a timer in -dealloc, access the ivar directly:
-(void)dealloc
{
[ _myTimer invalidate ] ; // don't use self.myTimer here, that would create a timer even though we're going away...
}
There are probably more use cases. For most properties you don't even need to use the ivar, just use <value> = self.property and self.property = <new value>.
edit:
Also, there will be some additional overhead for accessing the property via message dispatch (using dot-accessor syntax or the getter) vs directly accessing the ivar, but it will make no difference in almost all cases.