I am new to objective c. I create a property at .h header file of the class and then i synthesize.
What is the difference between
#synthesize propertyname;
and
#synthesize propertyname = _propertyname;
Both work but what is the purpose of using the first one or the second one.
Any help appreciated.
First of all you need not write #synthesize propertyname anymore.
In Objective-C when you declare a property, compiler auto generates its accessor methods for you by default. These accessor methods can be getter and setter if property is both read and write property else just a getter if it's a readonly property.
Compiler uses internal variables (called iVar) under the hood of these accessor methods implementation. (You can obviously provide your own implementation of these accessor methods and also provide your own internal variables as well)
What is the difference between #synthesize propertyname; and #synthesize propertyname = _propertyname;
when you declare a #synthesize propertyname; compiler auto generates and uses an iVar named propertyname and uses it in its default accessor implementation and you can also use it as propertyname in your .m file as compiler has already declared it for you.
property = #"abcd";
when you declare a #synthesize propertyname = _propertyname; compiler auto generates and uses a iVar named _propertyname and uses it in its default accessor implementation and you can also use it as _propertyname in your .m file as compiler has already declared it for you.
_property = #"abcd";
Broadly speaking the general difference between the two statement is just the change in name of iVar (usage of it are different though)
what is the purpose of using the first one or the second one.
As I already mentioned you need not use either of them in a normal usecase. Compiler already does that for you.
We used to write #synthesize propertyname; when we neither had any specific reservation about the name of ivar nor wanted to provide our own private variable as ivar to a specific property (Explained in detail below). This was simpler than explicitly specifying the name of iVar and we knew that compiler will generate an ivar with same name as property for us.
we typically wrote #synthesize propertyname = _propetyname when #synthesize propertyname; wasn't available or when we wanted our iVar to follow a specific nomenclature ('_' following name of property) or when we wanted to use our own private variable as iVar to a property.
In both the cases #synthesize was handy because it would relieve us from writing a boiler plate code like adding setter and getter methods for properties declared.
How to use custom variable as ivar for a property?
#interface SynthesizeExplorer : NSObject
#property (nonatomic,strong) NSString *name;
#end
#implementation SynthesizeExplorer
NSString *blaBlaName;
#synthesize name = blaBlaName;
#end
If you look at the implementation you will see that property name is backed by a internal variable named blaBlaName and not by the typical compiler generated ivar like name or _name.
As of today the only reason I see for the usage of #synthesize when you wanna use your custom internal variable to back the property you have declared. Otherwise I dont see any point in writing neither #synthesize propertyname; or #synthesize propertyname = _propertyname;
Related
I've been reading the tutorials and I'm right now designing the model's architecture, and since I'm new to Objective-C, I'm not sure if the standards are like Java where you have public setter/getter and private attribute. This is 1 question I'd like to ask.
If the standards are so, declaring private properties are done in the *.m file #interface, but how do I #syntetize a setter/getter and how do I call them from outside: is it like [object SetProperty:property] ?
If the standards are different, can I get an example of a model class?
Thanks in advance.
A property is essentially a promise that a class provides certain accessor methods. For example:
#property(strong, nonatomic) Foo *foo;
is a promise that the class provides -foo and -setFoo: methods. So, if you want the accessors to be public, declare the property in your class's public interface (i.e. in the header file) and be done with it.
It's true that the instance variable that backs that property (_foo, unless you specify a different name) will then be accessible, but it's very poor form to access another object's instance variables directly. Many things in Objective-C are governed by convention and that's generally enough to avoid problems. Also, a given property doesn't have to be backed by any instance variable at all: a property like fullName might be computed from other properties like firstName and lastName, so there's good reason beyond mere convention for clients to avoid accessing ivars directly.
The common approach if you want to give access to your attribute is to use the keyword #property in the .h file of your class to define a property. This will automatically define a setter and a getter and you don't need to synthesise your property as of Xcode 4.4.
Your private attribute will be accessible within your .m file and will have the name of your property with "_" as a prefix by default.
You can create a private property and create public setter/getter method of your own. From this method you can assign or retrieve the value back.
#interface Person : NSObject
-(void)setTheName:(NSString *)fullName;
-(NSString *)theName;
#end
Implementation file:
#import "Person.h"
#interface Person()
#property(atomic) NSString *fullName;
#end
#implementation Person
-(void)setTheName:(NSString *)fullName{
self.fullName = fullName;
}
-(NSString *)theName{
return self.fullName;
}
#end
In the above is private however you can check the selector still exists(but throws a warning)
if ([p respondsToSelector:#selector(setFullName:)]) {
[p performSelector:#selector(setFullName:) withObject:#"Anoop"];
}
NSLog(#">>>> %#",[p theName]);
Output will be :
>>>> Anoop
However it is seldom required to set any private property from outside. If that is the requirement we can make the property public.
Well it is true that Objective-C uses another terminology than most of the other languages like Java. If I get what you're asking, if you want a property to be directly available outside the class, the property must be declared in the .h file. However if you want to hide the implementation of your code, you can declare a property in the .m file and provide setters/getters to the outside world just returning the information you want to be visible.
The #synthesize clause is to me a simpifier. By synthesizing a property the getter/setter will be automatically implemented and you don't need to do it yourself.
Does this answer your question ?
Understand that declaring a property causes the compiler to create accessor for you . so if i require a pseudo private property personally I declare it in the implementation, if i need pseudo public property i declare it in the header. public getter / private setter can be handled as indicated below. There is no need to create your own setters and getters prefer using an attribute as it saves writing setters/getters ;
in the header (.h)
#interface Person : NSObject
#property (nonatomic, readonly) NSString *fullName;
#end
in the implementation file (.m)
#import "Person.h"
#interface Person()
#property (nonatomic, readwrite) NSString *fullName;
#end
#implementation Person
... whatever this class does
// self.fullName = #"John Doe";
#end
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).
If I have a #property which I didn't want to have backed via an ivar I simply omitted the #synthesize and had manual getters which returned a calculated value.
However, now since Xcode 4.4 if I don't specify #synthesize do compiler will automatically generate it. Does that mean it will also generate an ivar even do I don't need/use it?
I could eventually force to not auto-synthesize by using dynamic. However that would be wrong, since #dynamic is supposed to be used for turning off warnings if getter and setter are implemented somewhere else or during runtime.
In my working with this, I've noticed the following behavior.
If you have a readwrite property, don't have a #synthesize, have a getter and don't have a setter, then it will generate the iVar.
If you have a readwrite property, don't have a #synthesize, don't have a getter, and have a setter, then it will generate the iVar.
If you have a readwrite property, don't have a #synthesize and have both a getter and a setter, then it will not generate the iVar.
If you have a readonly property, don't have a #synthesize and don't have a getter, then it will generate the iVar.
If you have a readonly property, don't have a #synthesize and have a getter, then it will not generate the iVar.
From this, I think the general rule is that if you don't have a #synthesize, and have all the methods needed to fully implement the property, then it's assumed to be dynamic and doesn't generate the iVar.
At any rate, if you want to ensure that an iVar is not generated then declare it as #dynamic.
Clarification on #dynamic
From Declared Properties in The Objective-C Programming Language:
You use the #dynamic keyword to tell the compiler that you will fulfill the API contract implied by a property either by providing method implementations directly or at runtime using other mechanisms such as dynamic loading of code or dynamic method resolution.
To me this reads like it OK to mark a property as #dynamic even when you are directly implementing the getter and setter.
If you mark the property as readonly and implement the getter yourself, it seems that iVar will not be created.
Interface declaration:
#property (nonatomic, readonly) BOOL myBoolProp;
Impementation:
- (BOOL)myBoolProp {
return true;
}
Trying this:
- (void)viewDidLoad {
[super viewDidLoad];
_myBoolProp = true;
}
will generate an error: Use of undeclared identifier '_myBoolProp'
Removing the custom getter method also removes the error, appearing to demonstrate that the iVar has now been generated.
Yes - iVars are still generated by clang (not Xcode, as it is the IDE, clang is the complier that really matters).
If you really don't want iVars, and don't want an implementation, there is the somewhat archaic #dynamic keyword that will do what you want, or you can specify the property in a protocol, which doesn't make it auto-synthesized:
// .h
#property (nonatomic, retain) NSObject *someProp;
//.m
#dynamic someProp; // no iVars generated
// other solution
#protocol MyObjectProtcol<NSObject>
#property (nonatomic, retain) NSObject *someProp;
#end
// now, when you implement the MyObjectProtocol protocol, the property won't auto-synthesize.
Finally I'm transitioning to ARC. Sounds too late but all my projects have retrocompatiilty to 3.0 (any news about App Store unsupporting?) so I can't use it. But now I'm working in a new project with base deployment in iOS 5 so I'm using ARC.
My question is so simple. I'm used to declare private instance variables and public properties. For example:
#interface MyClass : NSObject {
#private
Var *aVar_;
Var *anotherVar_;
}
#property (nonatomic, readonly) Var *aVar;
#end
#implementation MyClass
#synthesize aVar = aVar_;
#end
Inside the class I work with instance variables, not properties.
But now I'm trying to avoid instance variables because I think there are not neccessary and redundant if I use proeprties, and I read time ago that is better to use properties instead of instance variable, but I'm not sure. That class now seems like that
#interface MyClass : NSObject
#property (nonatomic, readwrite, strong) Var *aVar;
#end
#interface MyClass()
#property (nonatomic, readwrite, strong) Var *anotherVar;
#end
#implementation MyClass
#synthesize aVar = aVar_;
#synthesize anotherVar = anotherVar_;
#end
In this case I'm still using instance variables (underscored) to manage my data because is less verbose and ARC takes into account all memory issues, but I don't know if that is correct.
Also I have another question. The property of aVar in the first chunk of code is readonly but if I use only properties I have to make that property readwrite. If I want to make the public property readonly, do I have to declare a public readonly property in the #interface and a private readwrite in private #interface?
Thank you so much.
The answer to your questions is somewhat complex, but generally you have the swing of it.
Since ARC does all the memory management for you, its often simpler to just use an ivar (private to the class, declared in the implementation) for your internal needs. In that case all usages just use the name.
With properties, you can as of Xcode 4.4 let Xcode synthesize the setter and getter, as well as the ivar. Auto-synthesized ivars are created with a leading "_" character.
You can define a property as readonly in the implementation, leave it as readonly, and set it in your code as '_foo = ....'. [Many on this site would consider this a bad practice, my point is you can do it.]
Xcode 4.4 has a warning titled "Implicit Synthesized Properties" with a default of NO. This creates a warning if you do not provide a #synthesize statement for each property, even though it will do the synthesis anyway.
Personally, I use ivars whenever I can, and only define properties when I need to either make something public to other classes, or I have categories declared in multiple files (in which case I put the interface declaration of the class extension in its own file along with properties defined in it.)
With the new Objective-C update you don't even need to synthesize the property. All you need to do is declare #property (strong, nonatomic) Var *aVar; and the compiler will automatically add the synthesizing, backing the self.aVar property with an _aVar instance variable.
If you declare a property, your implementation should generally use that property even though ARC reduces some of the memory management errors.
In init some prefer to avoid using properties because doing so might trigger KVO on an object (self) that is only partially initialized.
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.