I see someone writes codes like this
#interface SomeClass:<NSObject>{
NSString * _iVar;
}
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
But I always like write codes like this:
#interface SomeClass:<NSObject>
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
They all works fine, and I can use an instance someClass to get iVar "someClass.ivar".I just know why?
You now don't even have to synthesize the iVars anymore. The latest Xcode will automatically create a backing instance variable for each property, with the property name prefixed with an underscore.
In Objective-C when you are using anything via "." (dot syntax), it is accessing property. You have declared and synthesize a property with name iVar, so you can access it with someClass.iVar.
When you are declaring a property, a variable is automatically created with it. So, even if you do not create a variable, it will be there.
To avoid ambiguity, people are creating properties and iVar with different names. So, they can identify if the variable is being used or a property is being used. In that case people let the compiler know that a particular variable is associated with a property by low way:
#synthesize iVar = _iVar;
If you want access variable directly outside the class instead of property, you should use "->" (arrow syntax).
Related
i have property like this:#property (nonatomic, assign, readonly) CGRect frame;in the example.h file,i think this statement is to tell other class that the frame property is readonly and it also tell the compiler do not need to synthesize a setter method.
is that right to say that the class itself can use the instance variable _frame(the self.frame still can not use) in the .m file? if so,is there a better way to use this instance variable _frame? redeclare this property to readwrite in the class extension or redeclare the instance variable in class extension like this(i have found many guys write like this,but i do not understand what is the benefit of doing so?):
#interface example () {
CGRect _frame;
}
#end
#implementation example
or i just need do nothing?
My understanding about property as follows:
1.program find name of property in class of receiver when you take dot operator(.).
Like this: tt.frame (example* tt = [[example alloc] init];)
2.Then program find relationship between name of property(binding with synthesized method same name as name of property) and instance variable.
The way for that is: #synthesize frame=_frame;
(frame is name of property,_frame is instance variable. Binding name of property and instance variable.If you don't do like this,compiler will provide a instance variable (frame,then modify this frame, not _frame you designed.)when you choice 64-bit environment.Or compiler will give you a warning, if you choice 32-bit environment)
3.Call method for the real instance variable.
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 am trying to convert non-ARC project to use ARC but for some reason its complaining about
the use of all instance variables.
#property (nonatomic,retain)id myvariable;
results in
Error : "Use of undeclared variable _myvariable"
there are some places in my code where I don't want to modify retain count but do an assignment to the property. so I use an instance variable.
adding #syhtnesize myvariable =_myvariable resolves this problem but I am trying to figure out the right way to fix this.
Possible solutions:
1) Add synthesize
2) replace use of instance variable with self.myvariable and make property assigned.
EDIT:
Extension of problem ARC errors
With all the arc stuff
#property (nonatomic, strong) Something *myVariable;
is accessible by both
self.myVariable;
and
_myVariable;
No need to use #synthesize
It sounds like you've hit a backward compatibility feature.
Since Xcode 4.4 property declarations no longer require an #synthesize statement and without one the compiler auto-generates an _propertyName instance variable.
However with an #synthesize propertyName, as you would pre-Xcode 4.4, then the compiler will auto-generate an propertyName - note no underscore - instance variable.
The compiler messages warning you "Use of undeclared variable _myvariable" suggest you have switched the code to use underscores but still have some #synthesize myvariable statements.
Your use of #synthesize myvariable = _myvariable specifies the name to use for the instance variable directly, and so solves your problem, but removing the #synthesize completely is the usual approach.
It depends what you need. If you declare property:
#property (strong) NSString *myvariable;
And you want to change name of the private ivar to something different that _myvariable you have to add
#synthesize myvariable = _myVarNewName
but if you want to use exactly the same name with underscore on the front just remove #synthesize (works with iOS 6 and above) and the compiler do the rest so you can access the private variable like _myvariable or public like self.myvariable.
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.
I am following Big Nerd Ranch iOS Programming by Joe Conway and am kinda puzzled when I saw the following code.
WebViewController.h
#import <Foundation/Foundation.h>
#interface WebViewController : UIViewController
#property (nonatomic, readonly) UIWebView *webView;
#end
WebViewController.m
#import "WebViewController.h"
#implementation WebViewController
- (void)loadView
{
// Create an instance of UIWebView as large as the screen
// Tell web view to scale web content to fit within bounds of webview
}
- (UIWebView *)webView
{
return (UIWebView *)[self view];
}
#end
Shouldn't one synthesize the property declared in .h file? Xcode didn't give an warning either (which it usually does when I declare a property with synthesizing).
By the way, in the book, he also mentioned
In WebViewController.h, add a property (but not an instance variable)
Doesn't declaring a property automatically generate an instance variable for you? Let me know what I missed. Thanks.
This is a good question, and one to which I think the answer is a bit subtle and often not immediate to people starting out with Objective-C. First of all let's dispel a myth about properties. The myth is this:
Objective-C properties are related to instance variables.
This is not necessarily true. It is often true, but not true in every case. Here's what is true:
An Objective-C property declares a getter and a setter method
(Or in the case of a readonly property, just a getter). In particular when you declare a property called foo (for the sake of discussion, let's assume it's not readonly), the only thing you are really doing is telling the compiler that the class you're writing has a method called -foo and a method called -setFoo:. By adding an #synthesize foo; declaration into the .m file, you are telling the compiler to generate those methods itself. Here you are saying, "Compiler, create an instance variable (also called foo) and generate implementations for my -foo and setFoo: methods that access this instance variable. In particular, return the value of this variable in -foo and set the value of the variable in -setFoo:.
Note, it is not necessary to have the compiler synthesize the methods for you. Rather, you can write -foo and -setFoo: yourself. Furthermore, you are not in any way required to create an instance variable to support the implementation of these methods. You can write them however you wish.
To summarize: the #property only tells the compiler about the existence of the getter and setter methods. You can then either: #synthesize the methods in your .m or write the methods yourself.
This is because the "webView" getter method is implemented in the .m file and because of that, "#synthesize" isn't necessary.
If a "webView" method wasn't explictly created in code, then the compiler would complain about the property not being synthesized. Synthesizing a "read only" property, in this case, would only create a "getter" method which would do roughly the same thing you see in the code up there.
And yes, according to the Apple docs on declared properties, it says this about "#synthesize":
You use the #synthesize directive to tell the compiler that it should synthesize the setter and/or getter methods for a property if
you do not supply them within the #implementation block. The
#synthesize directive also synthesizes an appropriate instance
variable if it is not otherwise declared.