I'm working on one simple objective-c program which contain categories. My class .h:
#import <Foundation/Foundation.h>
#interface Fraction : NSObject
#property int numerator, denominator;
-(void)setNumerator:(int)n andDenominator:(int)d;
#end
In .m file I synthesized my numerator and denominator. In main.m created category of my Fraction class:
#import "Fraction.h"
#interface Fraction (MathOps)
-(Fraction *) add: (Fraction *) f;
#end
#implementation Fraction (MathOps)
-(Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
Fraction *result = [[Fraction alloc] init];
result.numerator = (numerator * f.denominator) +
(denominator * f.numerator);
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
#end
But my program does not see numerator and denominator in category's implementation section. Error "Use of undeclared identifier 'numerator'(the same for denominator). What am I doing wrong?
Use the properties instead of using the ivars directly:
result.numerator = (self.numerator * f.denominator) + (self.denominator * f.numerator);
result.denominator = self.denominator * f.denominator;
The instance variables aren't visible to your category because they're not declared in Fraction's interface -- they're only created when you #synthesize them in your implementation. That leads to the other possible solution, which is to declare the instance variables in Fraction's interface:
#interface Fraction : NSObject {
int numerator;
int denominator;
}
#property int numerator, denominator;
-(void)setNumerator:(int)n andDenominator:(int)d;
#end
Related
I wrote two programs during a training. But one exercise task drives me crazy. Not the task itself but the program and the behavior of it.
The first program is to calculate the BMI of a person. Here it works all fine.
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
// Erstellt eine Instanz von Person
Person *person = [[Person alloc]init];
// Gibt den Instanzvariablen interessante Werte
[person setWeightInKilos:93.2];
[person setHeightInMeters:1.8];
// Ruft die Methode bodyMassIndex auf
float bmi = [person bodyMassIndex];
NSLog(#"person (%dKg, %.2fm) has a BMI of %.2f", [person weightInKilos],
[person heightInMeters], bmi);
}
return 0;
}
Person.h
#interface Person : NSObject
{
// Sie hat zwei Instanzvariablen
float heightInMeters;
int weightInKilos;
}
// Sie können diese Instanzvariablen anhand folgender Methoden setzen
#property float heightInMeters;
#property int weightInKilos;
// Diese Methode berechnet den Body-Mass-Index
- (float)bodyMassIndex;
#end
Person.m
#import "Person.h"
#implementation Person
#synthesize heightInMeters, weightInKilos;
- (float)bodyMassIndex
{
float h = [self heightInMeters];
return [self weightInKilos] / (h * h);
}
#end
This program was written by the author of the training.
My task is to write a program what is equal.
In my opinion it looks exactly the same:
main.m
#import <Foundation/Foundation.h>
#import "StocksHolding.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
StocksHolding *stock1 = [[StocksHolding alloc]init];
[stock1 purchaseSharePrice:1];
/*Here I geht the error "Instance method '-purchaseSharePrice:' not found (return type
defaults to 'id')*/
NSLog(#"%i", [stock1 purchaseSharePrice]);
}
return 0;
}
StockHoldings.h
#import <Foundation/Foundation.h>
#interface StocksHolding : NSObject
{
int purchaseSharePrice;
float currentSharePrice;
int numberOfShares;
}
#property int purchaseSharePrice;
#property float currentSharePrice;
#property int numberOfShares;
- (float)costInDollars;
- (float)valueInDollars;
#end
StockHoldings.m
#import "StocksHolding.h"
#implementation StocksHolding
#synthesize purchaseSharePrice, currentSharePrice, numberOfShares;
- (float)costInDollars
{
return purchaseSharePrice * numberOfShares;
}
- (float)valueInDollars
{
return currentSharePrice * numberOfShares;
}
#end
AS you can see... almost no differences except the names of the variables and methods.
Where is the error?
I was sitting for 3 hours at this question.
Please give me a helping hand.
Thanks
Christian
The problem is that you are not using the generated setter method.
purchaseSharePrice is a property.
The default setter is setPurchaseSharePrice: and the default getter is purchaseSharePrice.
So you can just do this
[stock1 setPurchaseSharePrice:1];
or this
stock1.purchaseSharePrice = 1;
In addition, when you want to get the value using the generated getter you can do
int myPrice = [stock1 purchaseSharePrice];
or this
int myPrice = stock1.purchaseSharePrice;
As you can see for both setting and getting, having a property allows you to use dot syntax with the property name directly, while using method syntax requires you to use the method names generated by the property.
I have two properties "M" and "m", not the best coding style I know but bear with me. Assignment to these properties in the init method does not function properly. Here's the code in it's entirety:
#import "AppDelegate.h"
#interface Foo : NSObject
#property (nonatomic, assign) int M;
#property (nonatomic, assign) int m;
- (id)initWithM:(int)M m:(int)m;
#end
#implementation Foo
- (id)initWithM:(int)M m:(int)m {
if((self = [super init])) {
self.M = M;
printf("M = %d %d\n", M, self.M);
self.m = m;
printf("M = %d %d\n", M, self.M);
printf("m = %d %d\n", m, self.m);
}
return self;
}
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
Foo *f = [[Foo alloc] initWithM:2 m:1];
}
#end
And here is the output from the printf's:
M = 2 2
M = 2 1
m = 1 0
If I change "M" to "BAR" and "m" to "bar" it works as I would expect. Is there an explanation for this other than being a compiler bug?
Thanks.
#property int M;
#property int m;
both create
- (void)setM:(int)
If you really wanted to have both an m and an M property (which you definitely shouldn't) you can use
#property int M;
#property (setter = setLowerCaseM:, getter = lowerCaseM)int m;
I have a program which runs fine, but I get no print output even though I have a NSLog file in main.m Can you tell me what's wrong? Thank you.
main.m
#import <Foundation/Foundation.h>
#import "Stockholding.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
StockHolding *stockA;
StockHolding *stockB;
StockHolding *stockC;
[stockA setPurchaseSharePrice:2.40];
[stockA setCurrentSharePrice:3.12];
[stockA setNumberOfShares:40];
[stockB setPurchaseSharePrice:1.50];
[stockB setCurrentSharePrice:1.41];
[stockC setNumberOfShares:35];
[stockC setPurchaseSharePrice:1.10];
[stockC setCurrentSharePrice:1.20];
[stockC setNumberOfShares:60];
NSArray *holdings = [NSArray arrayWithObjects:stockA, stockB, stockC, nil];
for (StockHolding *n in holdings) {
// Call the methods
float cost = [n costInDollars];
float value = [n valueInDollars];
NSLog(#"Bought stock for $%.2f, It is now at $%.2f, I have %d shares, They cost me $%.2f, Now they are worth $%.2f", [n purchaseSharePrice], [n currentSharePrice], [n numberOfShares], cost, value);
}
}
return 0;
}
StockHolding.h
#import <Foundation/Foundation.h>
#interface StockHolding : NSObject {
float purchaseSharePrice;
float currentSharePrice;
int numberOfShares;
}
#property float purchaseSharePrice;
#property float currentSharePrice;
#property int numberOfShares;
-(float)costInDollars;
-(float)valueInDollars;
#end
StockHolding.m
#import "StockHolding.h"
#implementation StockHolding
#synthesize purchaseSharePrice, currentSharePrice, numberOfShares;
-(float)costInDollars
{
return (purchaseSharePrice * numberOfShares);
}
-(float)valueInDollars
{
return (currentSharePrice * numberOfShares);
}
#end
You haven't actually created any of those StockHolding objects. Thus, your array is empty, and the loop doesn't do anything.
StockHolding *stockA;
is just a declaration of a pointer. You need to create the object to which it points; the usual procedure is this:
StockHolding *stockA = [[StockHolding alloc] init];
Since, under ARC, object pointers are initialized to nil (which means "no object"), you are passing nil as all of the arguments to arrayWithObjects:. nil being the sentinel value meaning "there are no more arguments", the array is created without contents.
With an empty array, for (StockHolding *n in holdings) doesn't have anything to enumerate over, so none of the code in the body of the loop, including your NSLog(), gets executed.
I just started programming in objective-c(today) and I'm just doing some simple command line examples but I've already run into something that has stumped me. I am getting a compiler error on lines 5 & 6 in main. Here is my code:
Fraction Interface:
#import <Foundation/Foundation.h>
#interface Fraction : NSObject
{
int numerator, denominator;
}
-(void)print;
-(void)setDenominator;
-(void)setNumerator;
#end
Fraction implementation:
#import "Fraction.h"
#implementation Fraction
-(void)print {
NSLog(#"%i/%i",numerator,denominator);
}
-(void)setNumerator: (int) n {
numerator = n;
}
-(void)setDenominator: (int) d {
denominator = d;
}
#end
Main:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
#autoreleasepool {
Fraction *f1 = [[Fraction alloc] init];
Fraction *f2 = [[Fraction alloc] init];
}
return 0;
}
All 3 files are in the same folder. I'm using Xcode; if this is relevant information.
Looks like you forgot to add #import "Fraction.h" to the top of main.m, In the future adding the error you receive would be helpful.
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