What does #property in a header file mean in Obj C? - objective-c

I'm trying to learn objective C and I'm looking through some simple code to figure it out. Here's an example of a header file:
#import <Foundation/Foundation.h>
#class XYPoint;
#interface Rectangle: NSObject
{
int width;
int height;
XYPoint *origin;
}
#property int width, height;
-(XYPoint *) origin;
-(void) setOrigin: (XYPoint *) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
-(int) perimeter;
#end
Can anyone explain the meaning of the line "#property int width, height;"? Thanks!

The property syntax lets you declare a combination of a getter and a setter in a short syntax. In your code, the declaration creates four methods:
-(int) width;
-(void)setWidth:(int)val;
-(int) height;
-(void)setHeight:(int)val;
There is probably an implementation, too, which ties these methods to their "backing variables" with names width and height defined above; there may also be a #synthesize directive in the .m file.
In the current version of Objective-C the declaration of backing variables is unnecessary: all properties are synthesized by default, but you can provide your own implementations if you wish.
Properties support an alternative way of invoking getter and setter methods in Objective-C: in addition to the standard
int h = [point height];
[point setWidth:123];
you can write
int h = point.height;
point.width = 123;
It is not necessary to declare properties to use the dot syntax: you can call any value-returning method with no arguments or a setter method with a single argument using dot syntax.

It is just a way for other classes to refer to the private iVars declared between { and }.
Basically, it will create a getter and a setter, that, for primitive types like int will look like this:
- (int)width
{
return width;
}
- (void)setWidth:(int)width
{
_width = width;
}
And you can override these 2 methods if you want.
According to the conventions, the underlying instance variables should be prefixed with "_":
#interface Rectangle: NSObject
{
int _width;
int _height;
XYPoint *_origin;
}
If you do not declare them, the compiler does that for you, but be careful, in case you override both the getter and the setter, you need to add this kind of statements in the ".m" file:
#synthesize width = _width;
because in that case the compiler will not generate the "_width" ivar on your behalf.

Related

The underscore of an ivar got lost when referencing to it in a objective c subclass?

Here is the code:
Rectangle.h
#import <Foundation/Foundation.h>
#interface Rectangle : NSObject
#property int width;
#property int height;
- (int)area;
- (int)perimeter;
- (void)setWidth:(int)w andHeight:(int)h;
#end
Rectangle.m
#import "Rectangle.h"
#implementation Rectangle
- (int)area
{
return _width * _height;
}
- (int)perimeter
{
return (_width + _height) * 2;
}
- (void)setWidth:(int)w andHeight:(int)h
{
_width = w;
_height = h;
}
#end
Square.h
#import "Rectangle.h"
#interface Square : Rectangle
- (void)setSide:(int)a;
- (int)side;
#end
Square.m
#import "Square.h"
#implementation Square
- (void)setSide:(int)s
{
[self setWidth:s andHeight:s];
}
- (int)side
{
return self._width;
}
#end
The problem is happening in the - (int)side method of Square.m. It doesn't work unless I change self._width to self.width. Why is this though? When I made the property in Rectangle.h, I did not synthesize it in Rectangle.m, so the ivar _width was automatically created. Since the property was declared in .h, isn't the ivar public? Or is it not public and what I am actually seeing is the hidden getter of the property width? So is it really doing:
- (int)side
{
return [self width];
}
The dot notation has me confused as to if it is referring to the ivar, or the getter method of the property itself. Can someone clarify that there is not any width ivar?
The dot notation has me confused as to if it is referring to the ivar,
or the getter method of the property itself. Can someone clarify that
there is not any width ivar?
The dot notation refers to the property accessor, width in this case. That is,
int foo = someSquare.width;
is exactly the same as:
int foo = [someSquare width];
So, trying to use dot notation with a leading underscore, self._width, doesn't make sense because there is no property named _width. There is an instance variable named _width, but you don't access it using dot notation.
Since the property was declared in .h, isn't the ivar public?
Yes, the ivar is publicly accessible, and you can get to it using pointer notation:
int foo = self->_width;
but don't do that. Use the property accessor instead.

Why can't I use direct instance variable from parent class

#interface rectangle: NSObject
#property int width, height;
{
-(int) area;
-(int) perimeter;
-(void) setWidth: (int) w andHeight: (int) h;
}
#end
#implementation rectangle
#synthesize width, height;
...
...
#end
I made a square subclass of rectangle
#interface square: rectangle
-(void) setSide: (int) s;
-(int) side;
#end
#implementation square
-(void) setSide: (int) s
{
[self setWidth: s andHeight: s];
}
-(int) side
{
return self.width;
}
#end
My main question is this: Why can't I just do this
return width;
when I want to get the side of my square object.
I thought
#property int width, height;
is just a simplified from
#interface rectangle: NSObject
{
int width;
int height;
}
//getter/setter methods
...
#end
and in the book, if an instance variable is declared in #interface, it is inherited by its subclass. But, apparently,
return width;
doesn't seem to work. Why is this happening?
The problem is that synthesize of properties is part of the implementation, not the interface. The subclass can only rely on the interface.
For example, the #synthesize could have specified a different instance variable name (e.g. #synthesize width = _my_funky_width;) and the subclass would have no way of knowing what the actual instance variable was.

Beginners confusion about objective c, assignment, properties etc

Sorry I couldn't be more descriptive in the title. I know C++ and C#, and a bit of Java, and I am doing some Objective C tutorials and can't explain what is going on here.
I will show you an example:
Here is the header/interface of the rectangle class:
#import <Foundation/Foundation.h>
#class XYPoint;
#interface Rectangle : NSObject
#property int width, height;
-(int) area;
-(int) perimeter;
-(void) setW:(int)w andH:(int)h;
-(XYPoint *) origin;
-(void) setOrigin:(XYPoint*)pt;
#end
Here is the implementation:
#import "Rectangle.h"
#implementation Rectangle{
XYPoint *origin;
}
#synthesize width, height;
-(void) setW:(int)w andH:(int)h
{
width = w;
height = h;
}
-(int) area{
return width*height;
}
-(int) perimeter{
return (width+height)*2;
}
-(XYPoint *) origin{
return origin;
}
-(void) setOrigin:(XYPoint*)pt{
origin = pt;
}
#end
And here is my main program:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "XYPoint.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
Rectangle *r = [[Rectangle alloc]init];
XYPoint *p = [[XYPoint alloc]init];
[p setX:100 andY:300];
[r setW:6 andH:8];
r.origin = p;
NSLog(#"Width and height is %i %i", r.width, r.height);
NSLog(#"Origin is at %i,%i", r.origin.x, r.origin.y);
NSLog(#"Arear and perimeter are %i and %i", [r area], [r perimeter]);
}
return 0;
}
The line r.origin = p; confuses me. Exactly which origin is being referred to here? The getter method as defined in the interface, or the actual member variable which is declared in the implementation?
Note origin is not a property.
To be honest I expected an error. The main program should only see the getter method, but it doesn't seem like a getter method that returns something could be on the left hand side of an assignment operator. Or is the system somehow mapping that syntax to a call to setOrigin?
I had expected the only possible way to set the origin would be something like [r setOrigin: p]
I can see how something like r.width = 5 would work, as width as declared in the header as being a property, but I cannot see how r.origin = p works.
Can someone explain what is going on here?
Thanks.
Your guess is right - that syntax, called dot notation, is translated into a call to [r setOrigin:p] by the compiler. The general idea is that just like most other languages, you have getters and setters for object properties; in Objective-C, these are usually written as:
- (type)variableName;
- (void)setVariableName:(type)aVariable;
So long as your own code conforms to these conventions, you can use dot notation to both get and set variables on your classes, and trust that your methods are called.
There's obviously a lot more going on behind the scenes, so I hope this brief explanation is enough for you for now. If you're interested, though, you can look further into:
Synthesizing properties and what actually happens - methods of the form shown above are generated by the compiler, along with instance variables for actual data storage
Key-value coding, which takes advantage of these principles and conventions
Special cases for some types (for example, BOOL variables' getters are usually written as -isVariableName rather than -variableName), and how you can manage them with #property attributes
Yes, property accessors invoked by the dot notation are automagically traansformed to method calls by the compiler; thus
variable = object.property;
is equivalent to
variable = [object property];
and
object.property = variable;
is equivalent to
[object setProperty:variable];

Error with getter method in Objective-C

I am following along with a series of web tutorials relating to Objective-C and am now getting a "Accessing unknown origin getter method" error when i try to build my program (origin being a member of a Rectangle class that I created).
Here is my class titled PointXY:
#import <Foundation/Foundation.h>
#interface PointXY : NSObject
{
int x;
int y;
}
//Setters and Getters
#property int x;
#property int y;
//Methods
- (void) setXY : (int) xCO : (int) yCO;
#end
I then define a rectangle class, that has a member that is of type PointXY:
#import <Foundation/Foundation.h>
#class PointXY;
#interface rectangle : NSObject
{
float width;
float height;
PointXY * origin;
}
//Setters and Getters
#property float width, height;
//Instance Methods
- (float) getArea;
- (float) getPerimeter;
//We already have setters and getters defined for width
//and height. The below method is for illustration purposes
- (void) setHW: (float) h : (float) w;
//Methods to set and get origin values
- (PointXY *) getOrigin; //Returns a PointXY object
- (void) setOrigin : (PointXY *) point;
#end
I get the error in main, if i try to access the x or y property of my origin member via my NSLog statement:
#import <Foundation/Foundation.h>
#import "rectangle.h"
#import "PointXY.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Create an object
rectangle * myRectangle = [[rectangle alloc]init];
PointXY * rOrigin = [[PointXY alloc]init];
[rOrigin setXY:100 :100];
myRectangle.origin = rOrigin;
NSLog(#"The origin for the rectangle is %i, %i", myRectangle.origin.x, myRectangle.origin.y);
[pool drain];
return 0;
}
I understand that one cannot access the members without either explicitly defining a synthesized accessor or by creating a method to do just that and was surprised to see the author of the tutorial do the above with no issue.
Is the above even possible? Can I access myRectangle.origin.x without origin being synthesized in myRectangle or do I have something set up incorrectly.
Thanks for your time.
Origin is an instance variable you need to create an #property for it and synthesize it as you already know.
//Setters and Getters
#property float width, height;
#property PointXY *origin;
But without the property you could access the origin by doing this rectangle->origin but that defeats the purpose of encapsulation.
Edit- origin will need to be defined as #public or #package

Objective-C getter/ setter

I'm trying to work my way through an Objective-C tutorial. In the book there is this example:
#interface
{
int width;
int height;
XYPoint *origin;
}
#property int width, height;
I thought, "hey there's no getter/setter for the XYPoint object. The code does work though." Now i'm going maybe to answer my own question :).
I thinks its because "origin" is a pointer already, and whats happening under the hood with "width" and "height", is that there is going te be created a pointer to them..
Am i right, or am i talking BS :) ??
I just dont get it. here's main:
#import "Rectangle.h"
#import "XYPoint.h"
int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Rectangle *myRect = [[Rectangle alloc] init];
XYPoint *myPoint = [[XYPoint alloc] init];
[myPoint setX: 100 andY: 200];
[myRect setWidth: 5 andHeight: 8];
myRect.origin = myPoint;
NSLog (#"Rectangle w = %i, h = %i",
myRect.width, myRect.height);
NSLog (#"Origin at (%i, %i)",
myRect.origin.x, myRect.origin.y);
NSLog (#"Area = %i, Perimeter = %i",
[myRect area], [myRect perimeter]);
[myRect release];
[myPoint release];
[pool drain];
return 0;
}
And here's the Rectangle object:
#import "Rectangle.h"
#import "XYPoint.h"
#implementation Rectangle
#synthesize width, height;
-(void) setWidth: (int) w andHeight: (int) h
{
width = w;
height = h;
}
- (void) setOrigin: (XYPoint *) pt
{
origin = pt;
}
-(int) area
{
return width * height;
}
-(int) perimeter
{
return (width + height) * 2;
}
-(XYPoint *) origin
{
return origin;
}
#end
What i dont understand is this line in main: myRect.origin = myPoint; I did not make a setter for it..
BTW thanks for your fast reply's
What i dont understand is this line in main: myRect.origin = myPoint; I did not make a setter for it..
There is both a getter and a setter (collectively referred to as accessors) created for origin in the Rectangle class. If you have a look in the implementation for Rectangle, this is the getter:
-(XYPoint *) origin
{
return origin;
}
and this is the setter:
- (void) setOrigin: (XYPoint *) pt
{
origin = pt;
}
And as of Objective-C 2.0 calling:
myRect.origin = myPoint;
is equivalent to:
[myRect setOrigin:myPoint];
Declaring getters and setters using #property (and then implementing them using #synthesize) is only one way of declaring and creating accessors, and is there for a convenience if you have lots of properties to declare in the class interface. As Schildmeijer said, #property int width is equivalent to declaring two methods:
- (int)width;
- (void)setWidth:(int)newWidth;
Due to the dynamically-bound nature of Objective-C method calls, you don't even have to declare the getter and setter methods in the interface, although it is generally best practice to do so if you are advertising them as publicly available to other classes.
You can think of a property declaration as being equivalent to declaring two accessor methods. Thus
#property int width;
is equivalent to:
- (int)width;
- (void)setWidth:(int)newWidth;
//Rectangle.h
#import <Foundation/Foundation.h>
#interface Rectangle : NSObject
#property int Width;
#property int Height;
-(int)Area;
#end
//Rectangle.m
#import "Rectangle.h"
#implementation Rectangle
#synthesize Width;/*Will create value Width , Setter called"setWidth" and Getter called "Width"*/
#synthesize Height;/*Will create value Height , Setter called"setHeight" and Getter called "Height"*/
-(int)Area
{
return Width*Height;
}
#end
// main.m
#import <Cocoa/Cocoa.h>
#import "Rectangle.h"
int main(int argc, const char * argv[])
{
Rectangle *myRectangle = [Rectangle new];
myRectangle.Width=3;
myRectangle.Height=5;
printf("Area = %d\n",[myRectangle Area]);
//Or
[myRectangle setWidth:5];
[myRectangle setHeight:6];
printf("Area = %d\n",[myRectangle Area]);
}
If you want to make Getter only or rename getter and setter
• readonly
• getter = newGetterName
• setter = new SetterName
example
//Rectangle.h
#import <Foundation/Foundation.h>
#interface Rectangle : NSObject
#property (getter = getWidth) int Width;
#property (readonly) int Height;
#end
You don't say what code is working, or what your expectations are for "working".
The above interface will create simple accessor methods for width and height that can be called from other objects as [object setWidth:1]; or object.width = 1; - these two are analogous.
Origin is some other object type and is a pointer, yes. But you would still want to declare a property for it to generate accessor methods.
Getters and setters are mostly useful if you need to access an instance variable from another class or you're using bindings to get/set them. So my guess would be that you need this functionality for the width and height but not for the origin. Note that the getters/setters do not make pointers out of the integers as you stated might be the reason. Ints are ints and getters/setters do not change that.