Objective-C Address of property expression - objective-c

I need access address of property but have problem. example code is
#interface Rectangle : NSObject
{
SDL_Rect wall;
SDL_Rect ground;
}
#property SDL_Rect wall;
#property SDL_Rect ground;
#end
#implementation Rectangle
#synthesize x;
#synthesize y;
#end
#interface Graphics : NSObject
{
int w;
int h;
}
-(void) drawSurface
#end
#implementation Graphics
-(void) drawSurface
{
Rectangle *rect = [[Rectangle alloc] init];
SDL_BlitSurface(camera, NULL, background, &rect.wall);
}
#end
&rect.x is Address of property expression requested

As the comments suggest, you cannot take the address of a property. A property is really just a promise that the object in question provides accessors for some value. The value itself may or may not even exist in an instance variable. For example, the getter for a property called fullName might generate the required value on the fly by concatenating the values of firstName and lastName properties.
Since you need to pass the address of a SDL_Rect into SDL_BlitSurface(), you could first copy the necessary property into a local variable, and then pass the address of that variable:
Rectangle *rect = [[Rectangle alloc] init];
SDL_Rect wall = rect.wall;
SDL_BlitSurface(camera, NULL, background, &wall);
If you need to preserve the value left in wall after the call to SDL_BlitSurface(), copy it back again after the call:
rect.wall = wall;

I had a similar situation with subclasses needing to access a CGAffineTransform defined in the parent class. The answer came from #orpheist's answer to this question: Get the address of an Objective-c property (which is a C struct). It does involve adding a method to your Rectangle class.
#interface Rectangle : NSObject
{
NSRect wall;
NSRect ground;
}
#property NSRect wall;
#property NSRect ground;
#end
#implementation Rectangle
#synthesize wall = _wall; //x;
#synthesize ground = _ground; //y;
- (const NSRect *) addressOfWall {
return &_wall;
}
- (const NSRect *) addressOfGround {
return &_ground;
}
+(instancetype)standardRectangle
{
Rectangle *newInstance = [[self alloc] init];
newInstance.wall = NSMakeRect(0,0, 300, 100);
newInstance.ground = NSMakeRect(0 ,0, 300, 450);
return newInstance;
}
#end
Now you can use, for instance, addressOfWall thus:
- (void)testWall
{
Rectangle *rect = [Rectangle standardRectangle];
XCTAssertEqual(100, [rect addressOfWall]->size.height);
}

Address of property expression requested that means:
#preperty (nonatomic,copy) NSString *name;
if you want to get the address of self.name. You cannot write the code like this:
NSLog (#"%p",&(self.name));
Because in fact,self.name is getter method, like this:
- (NSString *)name {
return _name;
}
so you cannot get address of method.

Related

Properties and pointers

In Objective-C, I can't seem to be able to make a pointer to a property. For example:
I make a Class called Car which is a SubClass of SKSpriteNode.
One of the SKSpriteNode's properties is its position (a CGPoint).
Now for my Car class, I want to create 4 new properties called wheelPosition1, wheelPosition2, wheelPosition3, wheelPosition4 (which all are CGPoints)
Each of the wheelPosition properties are related to the position property of the Car (as the position property of the car will represent the centre whilst the wheels go out 1,1 in 4 directions) like this:
I want the wheelPosition properties to point to the address of the position property of the car whenever retrieving or setting their values...
Xcode doesn't let me do this, because the .position property is "temporary" - So I can't do something like:
CGPoint * x = &sprite.position;
In this example, the obvious solution would just to create a new Tyre class and create a node tree with 4 tyres... but this was only an example to illustrate my problem. This is just a generic problem I have found whilst programming - I can't get a variable to ever point to the property of another Object.
Right now I'm having to change my setter methods in the class to get around this which means that if I wanted to move the centre of the car somewhere else, it would be harder...
But is there another way which'll allow me to point to that property of the class?
At the request of a below comment here is the code:
#interface SomeClass : SKSpriteNode
#property CGPoint newNameForPositionProperty;
-(void) newPositionToPosition
#end
#implementation SomeClass
#synthesize newNameForPositionProperty;
-(void) newPositionToPosition {
newNameForPositionProperty = self.position;
}
#end
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
SomeClass *newObject = [[SomeClass alloc] init];
newObject.position = CGPointMake(100, 100 * sqrt(3.0));
[newObject newPositionToPosition];
NSLog(#"Original Position Property: (%f, %f)", newObject.position.x, newObject.position.y);
NSLog(#"New Position Property: (%f, %f)", newObject.newNameForPositionProperty.x, newObject.newNameForPositionProperty.y);
//Change Position
NSLog(#" ");
//
newObject.position = CGPointMake(100, 100);
NSLog(#"Original Position Property: (%f, %f)", newObject.position.x, newObject.position.y);
NSLog(#"New Position Property: (%f, %f)", newObject.newNameForPositionProperty.x, newObject.newNameForPositionProperty.y);
}
#end
Here is an example of how the code might be applied:
#interface SomeClass : SKSpriteNode
#property double modulus, argument;
-(void) positionToModulusArgument;
#end
#implementation SomeClass
#synthesize modulus, argument;
-(void) positionToModulusArgument {
modulus = sqrt(pow(self.position.x, 2) + pow(self.position.y, 2));
//Realistically I would split the argument into 4 cases to represent the 4 quadrants, but as this is only an example, I will assume that the position is only in the top right quadrant.
argument = atan(self.position.y / self.position.x);
}
#end
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
SomeClass *newObject = [[SomeClass alloc] init];
newObject.position = CGPointMake(100, 100 * sqrt(3.0));
[newObject positionToModulusArgument];
NSLog(#"Cartesian Form: (%f, %f)", newObject.position.x, newObject.position.y);
NSLog(#"Polar Form: (%f, %f)",newObject.modulus, newObject.argument);
//Change Position
NSLog(#" ");
//
newObject.position = CGPointMake(100, 100);
NSLog(#"Cartesian Form: (%f, %f)", newObject.position.x, newObject.position.y);
NSLog(#"Polar Form: (%f, %f)",newObject.modulus, newObject.argument);
}
#end
In either case, the property doesn't change when the other does.
Your approach is wrong. You do not need a pointer. Simply calculate the wheel positions from the (center) position using self.position. You need the indirection of pointers, if the property that should be use can change (not its value, but the property itself), i. e. from position to anotherPosition.
However, you do not apply the address operator to the property's ivar, but to the return value of the getter -position. Return values are temporary. If you want to have a pointer to the ivar itself, use &_position.
But as I said: Don't do this at all.

Create a subclass of a SKSpriteNode subclass

Let's say I want to create a bunch of different types of Spaceships. I want to setup a base spaceship class that I can use to create other spaceships with minor differences.
My base class looks like this.
// BaseSpaceship.h
#interface SpaceshipNode : SKSpriteNode
#property NSColor color;
#property CGFloat engineThrust;
+ (id)baseSpaceshipWithImageNamed:(NSString *)name;
#end
// BaseSpaceship.m
#implementation BaseSpaceship
+ (id)baseSpaceshipWithImageNamed:(NSString *)name {
BaseSpaceship *ship = [BaseSpaceship spriteNodeWithImageNamed:name];
ship.color = [NSColor redColor];
ship.engineThrust = 2.0;
return ship;
}
#end
I can create a ship in MyScene.m like this just fine.
BaseSpaceship *baseClass = [BaseSpaceship baseSpaceshipWithImageNamed:#"BaseShip"];
However, I'm not sure how to create a subclass of BaseSpaceship, for example, DestroyerSpaceship. I'm not sure if I should be using static methods or not. The examples I've seen online use static methods to instantiate SKSpriteNodes. This is what I came up with, but it's wrong.
// DestroyerSpaceship.h
#interface DestroyerSpaceship : BaseSpaceship
#property CGFloat missileThrust;
- (id)makeDestroyerSpaceship;
#end
// DestroyerSpaceship.m
#implementation DestroyerSpaceship
- (id)makeDestroyerSpaceship{
DestroyerSpaceship *ship = [DestroyerSpaceship baseSpaceshipWithImageNamed:#"DestroyerShip"];
ship.engineThrust = 2.0;
// ship doesn't have missileThrust, program crashes
ship.missileThrust = 3.0;
return ship;
}
#end
Ultimately, I want to be able to do something like this.
DestroyerSpaceship* a = [DestroyerSpaceship makeDestroyerSpaceship];
EvilSpaceship* b = [EvilSpaceship makeEvilSpaceship];
NiceSpaceship* c = [NiceSpaceship makeNiceSpaceship];
And have them all inherit basic properties and methods from BaseSpaceship.
The answer is less complex than you think. Well, the code might be a bit more complex, but once you have the structure it is most flexible. Creating the different types of spaceships will also be a lot more readable.
You can override the initializer method in the subclass. As a sidenote, use (instancetype) instead of (id) (source: instancetype # NSHipster).
As you are adding custom body sprites to the object, I would opt to subclass SKNode instead of SKSpriteNode (so #interface SpaceshipNode : SKNode instead of #interface SpaceshipNode : SKSpriteNode).
#interface SpaceshipNode : SKNode
#property SKColor * color; // Use SKColor instead of NSColor
#property CGFloat engineThrust;
#end
// ...
#implementation SpaceshipNode
- (instancetype) init {
if (self == [super init]) {
NSLog(#"A new SpaceshipNode was just init'ed.");
// set some default initial values here that all brand-new SpaceshipNodes will inherit
// perhaps create and add a basic body sprite
// SKSpriteNode * body = ...;
// [self addChild:body];
// set thrust
self.engineThrust = 2.0;
}
return self;
}
Then you can subclass and create a new type of spaceship. Awesome!
#interface DestroyerSpaceship : SpaceshipNode
#property CGFloat missileThrust;
#end
#implementation DestroyerSpaceship
- (instancetype) init {
// note that [super init] will call the SpaceshipNode's init method
if (self = [super init]) {
NSLog(#"A new DestroyerSpaceship was just init'ed.");
// add a body sprite
// SKSpriteNode * body = ...;
// [self addChild:body];
// a Destroyer is much faster than your average spaceship
self.engineThrust = 10.0;
// set class specific variables
self.missileThrust = 5.f;
}
return self;
}
Now, you can just call:
SpaceshipNode * newSpaceShip = [SpaceshipNode new]; // short for [[SpaceshipNode alloc] init];
DestroyerSpaceship * newDestroyer = [DestroyerSpaceship new];
These two lines will log the following. The last two lines are caused by the Destroyer, which first calls the SpaceshipNode init, and then the Destroyer-specific init method.
A new SpaceshipNode was just init'ed.
A new SpaceshipNode was just init'ed.
A new DestroyerSpaceship was just init'ed.
And you can even use it like this:
SpaceshipNode * newUnidentifiedVessel = [DestroyerSpaceship new];
if ([newUnidentifiedVessel isKindOfClass:[DestroyerSpaceship class]]) {
NSLog(#"We are under attack! Route power to shields!");
}
- (instancetype)makeDestroyerSpaceship{
if (self = [super baseSpaceshipWithImageNamed:#"DestroyerShip"]) {
self.engineThrust = 2.0;
self.missileThrust = 3.0;
}
return self;
}

imageitem class define

i need to build an application that define an array that should be made of image items.
every image iten has an image, a name and a photographer name.
i build my image item class and i want you to check if my define is correct and good(i just start to learn objective c).
i want you to emphasize on the set's methods.
here is the photoitem.h:
#import <Foundation/Foundation.h>
#interface photoItem : NSObject
{
UIImage *imageView;
NSString *photoNameLabel;
NSString *photographerNameLabel;
UIButton *viewPhoto;
}
#property(readonly) NSString *name;
#property(readonly) NSString *nameOfPhotographer;
#property(readonly) UIImage *imageItem;
-(id)makePhotoItemWIthPhoto:(UIImage*)image name:(NSString*)photoName photographer: (NSString*)photographerName;
#end
here is my photoitem.m:
#import "photoItem.h"
#implementation photoItem
#synthesize name;
#synthesize nameOfPhotographer;
#synthesize imageItem;
-(id)makePhotoItemWIthPhoto:(UIImage*)image name:(NSString*)photoName photographer:(NSString*)photographerName
{
[self setName:photoName];
[self setNameOfPhotographer:photographerName];
[self setImageItem:image];
return self;
}
-(void) setName:(NSString *)name
{
photoNameLabel = name;
}
-(void) setNameOfPhotographer:(NSString *)nameOfPhotographer
{
photographerNameLabel = nameOfPhotographer;
}
-(void)setImageItem:(UIImage *)imageItem
{
imageView = imageItem;
}
#end
i hope you could fix my errors(if there are some).
thanks.
Two problems come to mind:
1) -(id)makePhotoItemWIthPhoto:name:photographer: might be better as -(id)initWithPhoto:name:photographer:. Otherwise the caller needs to alloc and init an object first so that self is valid, then call your method. At that point, the return of self doesn't make sense.
Example:
-(idinitWithPhoto:(UIImage*)image name:(NSString*)photoName photographer:(NSString*)photographerName {
self = [super init];
if (self) {
[self setName:photoName];
[self setNameOfPhotographer:photographerName];
[self setImageItem:image];
}
return self;
}
2) The three readonly properties don't seem to have any purpose since they have no connection to the variables that you initialize in the makePhotoItemWIthPhoto: method.

i try to understand initializers in obj-c and i can't

I try to understand how to work simple init funcion and I don't know where I have made a mistake. Can somebody assist?
Rectangle.h
#interface Rectangle : NSObject
{
int width;
int height;
}
-(id)initObject;
#end
Rectangle.m
#implementation Rectangle
-(id)initObject{
if (self = [super init]) {
height = 5;
width = 7;
}
return self;
}
#end
And in ViewController.h i import Rectangle.h, declare *rect object and in .m i execute(? run?) initObject.
ViewController.h
#import <UIKit/UIKit.h>
#import "Rectangle.h"
#interface ViewController : UIViewController
{
Rectangle *rect;
}
#end
ViewController.m
-(void)viewDidLoad
{
rect = [[Rectangle alloc] initObject];
NSLog(#"%#", rect);
[super viewDidLoad];
}
initObject return me:
2011-11-21 09:43:02.625 initializers[43693:f803] <Rectangle: 0x6ab1660>
The only problem with your code that I can see is you called your initializer -initObject for no good reason. It's not taking any parameters at all, so you really should just call it -init like every other parameterless initializer in the system.
As for the log output, I imagine your confusion lies in the fact that it says <Rectangle: 0x6ab1660>. This is perfectly normal. The default implementation of -description (the method that returns this output) is the name of the class of the object followed by the object's address. In other words, -[NSObject description] is likely to be implemented something like the following:
- (NSString *)description {
return [NSString stringWithFormat:#"<%#: %p>",
NSStringFromClass([self class]),
self];
}
This means that instance variables of your object are not going to be printed. A number of built-in classes do print their instance variables when logged, but this was implemented specifically for that class and is not a generic mechanism. If you want to verify that your Rectangle object is correct, you could implement -description like so:
- (NSString *)description {
return [NSString stringWithFormat:#"<%#: %p width=%d, height=%d>",
NSStringFromClass([self class]),
self,
width,
height];
}
No error! Since your Rectangle class has no description method, calling NSLog(#"%#", rect); will return the class of the object, followed by its address in memory.
If you want to print width and height of the rectangle you may use something like:
in Rectangle.h
#interface Rectangle : NSObject
{
int width;
int height;
}
-(id)initObject;
#property int width, height;
#end
in Rectangle.m
#implementation Rectangle
#synthesize width, height;
-(id)initObject{
if (self = [super init]) {
height = 5;
width = 7;
}
return self;
}
#end
and then call
NSLog(#"width=%d, height=%d", [rect width], [rect height]);

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.