I`m new to the Objective-C world, so I have a couple of questions about class member declarations. Please notice the comments in the code below:
In header file I have code such
#interface MyClass : NSObject {
//what we points here ? Object or something else ?
NSString *myString;
}
// In interface we declare NSTring *myString in #property declaration is (NSString *) myString.
// What is the difference here ? Why we don`t use the same declaration as above ?
#property(nonatomic, retain) (NSString *) myString;
#end
The thing you're missing is that instance variables (defined between curly braces) are not accessed from the outside (i.e. other objects). To do that - you have to define a property for the instance var (by using #property keyword) to know how outside objects can access a value of given instance var. Also in implementation file (.m) you have to #synthesize instance variable accessor methods for it's appropriate property. Please note that #property declaration not only defines what it holds (NSString *myString), but also how it's being accessed and set. You can define property as read only (#property (readonly)...) or accessible from few threads at a time (#property (nonatomic)).
Also - if your instance var is named differently from the property it represents to other objects - you must show that in implementation file (#synthesize propertyName=instanveVariableName)
update
MyClass *myInstance = [[MyClass alloc] init];
[myInstance myString]; // returns myString property
Try running above 2 lines of code without #property and you'll see the difference.
Actually you are defining a Property of yar class.#interface MyClass : NSObject {
//public object
#public
NSString *myString;
//private object
NSString *myString2;
}
class structure for obj-c
.h file
#interface MyClass : NSObject {
//Your member variable;
// you member objects;
}
//property declarations
//function declarations
#end
so it should look like
#interface MyClass : NSObject {
NSString *str;
}
#property(nanatomic,retain) NSString *str;
-(void)method;
#end
Related
I do not quite understand the way of declaring instance variable and property. Can someone explain in detail the difference of the two codes below? In the second method, if I use _name for instance variable, is it the same function as the way declaring name in first code? Thanks!
First Code:
// OrderItem.h
#import <Foundation/Foundation.h>
#interface OrderItem : NSObject
{
#public NSString *name;
}
-(id) initWithItemName: (NSString *) itemName;
#end
// OrderItem.m
#import "OrderItem.h"
#implementation OrderItem
-(id) initWithItemName: (NSString *) itemName {
self = [super init];
if (self) {
name = itemName;
NSLog(#"Initializing OrderItem");
}
return self;
}
#end
Second Code:
// OrderItem.h
#import <Foundation/Foundation.h>
#interface OrderItem : NSObject
#property (strong,nonatomic) NSString *name;
-(id) initWithItemName: (NSString *) itemName;
#end
// OrderItem.m
#import "OrderItem.h"
#implementation OrderItem
-(id) initWithItemName: (NSString *) itemName {
self = [super init];
if (self) {
_name = itemName;
NSLog(#"Initializing OrderItem");
}
return self;
}
#end
In the first case you have declared an instance variable (usually called an ivar in Objective-C).
In the second case you have declared a property. A property is a set of two methods, a getter and a setter, usually accessed using dot notation, e.g. self.name. However, an ivar is automatically synthesized for the property with the name _name. That instance variable is what you are accessing in your init.
You can actually change the name of the ivar using #synthesize name = _myName or not have it at all (if you declare the getter and setter manually, no ivar will be synthesized).
Objective-C properties are a rather complicated topic so don't worry if you don't understand it immediately.
Properties are public which means that other classes can read and write them (even classes that aren't subclasses of the class that declares the property). In addition to that, properties provide a getter and a setter method (mutator methods). The getter of a property gets called every time you access the property
NSString *aName = self.name;
Whereas the setter is accessed every time you write or assign to a property.
self.name = #"Some name";
Instance variables (or ivars) are, by default, only visible for the class that declares it and its subclasses (also known as being encapsulated by their class). You can change this default behavior when you add the keyword #public to your ivar declaration though.
From the developer that started to learn objective-c two days ago, I don't understand the difference between the following two methods :
1.
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
2.
#interface Person : NSObject{
NSString *firstName;
NSString *lastName;
}
#end
Using Java-Language,we define two String Field:
class Person extends Object{
(public/private/protected) String firstName;
(public/private/protected) String lastName;
}
I want to know which one(between 1 and 2) has same meaning with the Java code above.
Very thanks for #iamyogish #Popeye,if my answer is right i will correct both of you.
After read the eBook: Objective-C 2.0 Essentials,I learned that(if it is not right,you tell me. ):
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
this is equivalent to the Java Code:
class Person extends Object{
private String firstName;
private String lastName;//In fact:private should be protected
//setter and getter.
//you can use ecplise tool to generate setter/getter method automaticly
}
As you can probably imagine, having to write these methods for large numbers(1000 or more.)of complex classes will ultimately prove to be time consuming. Objective-C provides synthesized accessor methods,so what you should is use of the #property and #synthesize directives.if you write your code like this:
#interface Person : NSObject
NSString *firstName;//note that the default access level is protected.
NSString *lastName;
#end
Unfortunatly, you need to provide methods that can access instance variables,such as(you can define the name of the function by yourself)
-(NSString ) getFirstName;
-(NSString ) getLastName;
-(void) setFirstName:(NSString * name);
-(void) setLastName:(NSString * name);
In addition to this,if the #property and #synthesize directives are used,you can access instance variables like C++/JAVA syntax dot notationsuch as:
NSString * firstName= [[Person alloc] init].firstName;
Note that: A key point to understand about dot notation is that it only works for instance variables for which synthesized accessor methods have been declared.
The access level for instance variables is specified in the #interface section of the class declaration using the #protected, #private and #public directives.
#interface Person : NSObject
#public
NSString *firstName;//note that the default access level is protected.
NSString *lastName;
#end
When accessing a public instance variable from another class or any other code in a methods or function, the -> pointer operator notation is used. So you can access the Public Filed in C++/C like:
[[Person alloc] init]->firstName = "your first name";
Another question is:
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
is is equivalent to:
#interface Person : NSObject{
NSString *firstName;
NSString *lastName;
}
#property NSString *firstName;
#property NSString *lastName;
#end
or not? and ivar is equivalent to instance variable or not?
Lets start with (2)
#interface Person : NSObject
{
NSString *firstName;
NSString *lastName;
}
#end
In this case firstName and lastName are know as ivars or Instance Variables for me I don't generally declare ivars. Some developers now say that you shouldn't put these in the #interface declaration for two reason.
It exposes details about the implementation to users of the class, this will lead other developers who or using and in some cases yourself to rely on implementation details that should be available to them.
Some developers believe that putting these in the #interface can make compile times significantly longer.
Most developers believe that the best way to implement an ivar is within the #implementation where braces are being used like:
#implementation Person {
NSString *firstName;
NSString *lastName;
}
The theory behind why we put them here is because theoretically they are declared private, preventing anyone from knowing about them except the developer who created the class. This will resolve all other developers from messing around with things they shouldn't.
The equivalent to this in Java is just as simple as private String firstName;
Now lets take a look at (1)
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
Technically #properties need only be used when the property needs to be accessible from other classes, but many developers prefer to use these over ivars as it makes them easier to use, and in new versions of xcode the ivars for these properties are declared automatically in the background.
By declaring a property you are basically automatically generating the getters and setters for these properties. In earlier versions of xcode you did have to #synthesize but there is no need for this anymore. So declaring the two properties firstName and lastName this will generate in the background
- (void)setFirstName:(NSString *)aFirstName
{
self.firstName = aFirstName;
}
- (NSString *)firstName
{
// Note in objective-c we don't generally use `get`
return self.firstName;
}
- (void)setLastName:(NSString *)aLastName
{
self.lastName= aLastName;
}
- (NSString *)lastName
{
// Note in objective-c we don't generally use `get`
return self.lastName;
}
When it comes to comparing this to Java this is near enough the same as
private String firstName;
public void setFirstName(String aFirstName) {
this.firstName = aFirstName;
}
public String getFirstName() {
return this.firstName;
}
We create out instance variable the same way we would do it as if it was a normal ivar but there is nothing to say create my setters and getters in java so we have to do that ourselves. Note that the ivar here in java is still private it is the getters and setters that we are opening up to others.
There is a sort of third option that you have missed as well. Due to the conventions in objective-c what would happen with a #property for a bool?
We have it declared like
#property (nonatomic) BOOL personForObject;
in objective-c when it comes to bools the getter is slightly different in name. Whilst we are happy with the synthesized setter of
- (void)setPersonForObject:(BOOL)aPersonForObject
{
self.personForObject = aPersonForObject;
}
we aren't happy though with the getter, when it comes to bools the getters should start with is so personForObjects getter should be isPersonForObject but the synthesize doesn't know this so will automatically generate the getter the other way. So we need to tell it in the property declaration like
#property (nonatomic, getter=isPersonForObject) BOOL personForObject;
You will now have to implement this method yourself though like
- (BOOL)isPersonForObject
{
return self.personForObject;
}
Note this only need be done if you choice to ignore convention which I wouldn't recommend.
Any questions just ask.
The code number two is equivalent to the Java version.
A #property in the most complete version defines the getter, setter and instance variable. You can also modify the declaration to specify only a getter, only a setter or to specify a different instance variable.
#property is shorthand for defining an instance variable and its corresponding accessors.
If you just define instance variables in the interface, you will not get the accessor methods.
See whenever you declare members in objective-C you should provide getters and setters for those members(Variables). But Objective-C supports something called synthesized accessors using the directives #property and #synthesize.
Now lets see program with synthesized accessors :
#import<Foundation/Foundation.h>
#interface Person : NSObject{
NSString * firstName;// declaring that Person class as variable firstName
NSString * lastName;// // declaring that Person class as variable lastName
}
#property NSString *firstName; // says to compiler that we want to define synthesized accesor for the firstName
#property NSString *lastName;// says to compiler that we want to define synthesized accesor for the lastName
#end
#implementation Person
#synthesize firstName, lastName;// synthesized accessor to be defined for firstName and lastName
#end;
int main(){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
Person * p = [[Person alloc]init] ;
[p setFirstName:#"Yogish"]; // method setFirstName is implicitly defined by compiler
[p setLastName:#"Gowda"];// method setLastName is implicitly defined by compiler
NSLog(#"%#",p.firstName);
NSLog(#"%#",p.lastName);
[pool drain];
return 0;
}
Now coming back if u haven't used the #property and #synthesize you should have to write your own setters and getters method to set and get the members firstName and lastName. Since you're using #property and #synthesize the compiler will write getters and setter methods .
Hope this helps :)
I have got a header file (.h) and I want to declare name but all these ways work the same I think because I haven't seen any difference with functionality. Could you tell me what the difference is between:
This with both declarations:
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Without variable:
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Or Without property:
#interface someClass : UIViewController
{
NSString *name;
}
#end
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Doing this you will explicitly declare both a property and an ivar.
A property is just a set of methods:
- (void)setName:(NSString*)name;
- (NSString*)name;
An ivar is the memory store holding the value that the property methods manage. This allows you to do:
self.name = ... // access through setter method
name = ... // direct access
The advantage of using properties is that they deal with memory management for you. E.g., in your case, the property is of type copy: this means that with the first syntax (self.name = ...) a copy of the object will be done. If not using properties, you would explicitly need to do: name = [originalString copy]; to obtain the same effect.
Other options you can specify for properties (but not ivars) are: strong and weak ownerships.
Furthermore, a property also represents a public interface to access the variable from outside your class.
Using direct access you are on your own as to memory management (if you are not using ARC).
If you are using ARC and don't define properties, you will not be able to control how the memory is managed by specifying the ownership: strong, weak, retain).
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Here you only declare the properties; the ivar is "inferred" by the #synthesize directive in your implementation file. This is only possible in Objective C 2.0 and later (previously, the ivar declaration as above was mandatory).
The same considerations as above applies, with a minor nuance: with older versions of LLVM (ObjC compiler) you will not be able to reference directly the auto-synthesized ivar; with current version of LLVM, if you omit the #synthesize directive, then an automatic ivar named after your property would also be declared (in your case it would be _name).
This last paragraph may seem a bit "advanced", or contrived, but you can safely ignore it.
#interface someClass : UIViewController
{
NSString *name;
}
#end
In this case you are only declaring the ivar. No accessor methods. You will need to handle memory management on your own (if not using ARC), futhermore you will not be able to access the variable from outside the class. For that you need accessors.
Hope this helps.
Case 1:
The is the old method, here the #property and variable are not related until you #synthesize name = name;
Access methods :
variable : name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
With the latest xcode just the property is enough.
Case 2:
the new xcode style. Here the synthesize and variable creation is taken care by the compiler. (so less 2 lines of code and this also helps with memory management)
Access methods :
variable : _name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
Case 3:
Here the name is just a variable and it dose not have a setter or a getter.
with out property (or) setter & getter this is as good as a local variable and it cannot be accessed from other objects.
Here's a (reduced) class declaration from an example on apple's developer:
#interface myController : UITableViewController {
NSArray *samples;
}
#property (nonatomic, retain) NSArray *samples
What is the purpose of declaring
{
NSArray *samples;
}
when you declare it again as a property? If you leave out:
{
NSArray *samples;
}
you can still use #synthesize in your .m and get a reference to it!
I'm a little confused as to the purpose of the first declaration.
Thanks
Properties are just a handy way to declare accessors to you data. It usually leads to some member variable but not necessarily. And that member var can have different name:
#interface myController : UITableViewController {
NSArray *mSamples;
}
#property (nonatomic, retain) NSArray *samples
#end
#implementation
#synthesize samples = mSamples;
#end
Or you can use properties without vars at all:
#interface myController : UITableViewController {
}
#property (nonatomic, retain) NSArray *samples
#end
#implementation
-(NSArray*) samples {
//you can for example read some array from file and return it
}
-(void) setSamples:(NSArray*) arr {
//write that array to file or whatever you want
}
#end
With new compiler you can use properties without ivars at all, compiler will generate them for you implicitly.
With a property declaration, there is no purpose or benefit in explicitly declaring the backing instance variable. It's just leftovers from habit.
Edit: For iOS or Mac 64-bit Intel, explicitly declaring ivars was never needed for properties. But they were needed for other Mac work — hence the examples.
Also, I did find a difference. When an ivar is explicitly declared, unless you state otherwise, it is a protected ivar, available to subclasses. But when an ivar is implicitly created for a property, subclasses don't have access to the ivar.
In Objective-c 2.0 why do subclasses need to reference instance variables in parent classes using the self keyword?
Consider this example:
// a.h
#interface MyClass : NSObject
#property (nonatomic, retain) Object *myObject;
#end
// a.m
#implementation MyClass
#synthesize myObject;
#end
// b.h
#interface AnotherClass : MyClass
#end
// b.m
#implementation AnotherClass
- (void) someMethod {
// error
// Object *obj = myObject;
// works
// Object *obj = self.myObject;
}
#end
You haven't actually defined a variable, you only defined a property (which implicitly defines a variable that is private). And since property are just method, you need the dot syntax. Note that self.property is the same as [self property].
To fix this, specify a variable. I'll give you an example where the variable has a different name than the property. Most people chose the same name for both but I like to have them differ so I immediately see which one is meant.
// a.h
#interface MyClass : NSObject {
// Instance variables are "protected" by default, except if you
// use #private or #public.
Object *myObjectVar;
}
#property (nonatomic, retain) Object *myObject;
#end
// a.m
#implementation MyClass
#synthesize myObject = myObjectVar;
#end
// b.h
#interface AnotherClass : MyClass
#end
// b.m
#implementation AnotherClass
- (void) someMethod {
// works
Object *obj = myObjectVar;
// works
obj = self.myObject;
// the same as self.myObject
obj = [self myObject];
}
#end
Note the difference when you assign: if you assign to your variable the object is not retained automatically. But it is retained if you use the property:
myObjectVar = someObject; // not retained, old object not released!
self.myObject = someObject; // old object released, new object retained
[self setMyObject:someObject]; // same as the line above
Edit: Mentioned that the synthesized instance variables are private by default, as noted by #Jason Coco. And #NSGod is right that normal instance variables are protected by default rather than public, fixed that.
They don't, provided you actually declare an instance variable in the superclass, rather than rely on the new runtime's ability to synthesize the instance variable (in addition to synthesizing the accessor methods). See The Objective-C Programming Language: Runtime Difference for more info on instance variable synthesis.
For example, to be able to refer to the instance variable directly, you'd need to change the following:
#interface MyClass : NSObject
#property (nonatomic, retain) Object *myObject;
#end
to:
#interface MyClass : NSObject {
// there is an implied #protected directive here
Object *myObject;
}
#property (nonatomic, retain) Object *myObject;
#end
By default, instance variables are #protected, meaning the class and any subclasses can access the instance variables directly. #protected ivars differ from #public ivars in that you can't access them using ->. #private ivars can only be accessed by the class that declares them. See The Objective-C Programming Language: The Scope of Instance Variables for more info.