I am new to Obejctive-C as well as Mac. I have been trying to learn online and have written this simple piece of code , but the NSLog doesn't work for me.
#import <Foundation/Foundation.h>
#interface Person : NSObject{
int age ;
int weight;
}
-(void) print;
-(void) setAge:(int) a;
-(void) setWeight:(int) w;
#end
//---implementation---
#implementation Person
-(void) print{
NSLog(#"I am %i years and my weight is %i",age,weight);
}
-(void) setAge:(int) a{
age = a;
}
-(void) setWeight:(int) w{
weight = w;
}
#end
int main(int argc, char *argV[]){
Person *test;
test = [test init];
[test setAge:25];
[test setWeight:75];
[test print];
return 0;
}
When I run the program the output console disappears as shown in the top right hand corner. When I display the output console by explicitly clicking on the same, I can see the program exited with code 0(successful output?) but NSLog not printed.
Let me know if I am doing some rookie mistake :)
test = [test init];
needs to be:
test = [[Person alloc] init];
You always need to alloc then init. And you need to specify the class name
You need two write:
Person *test = [[Person alloc] init];
You need this code.
Person *test = [Person new ];
Related
#import <Foundation/Foundation.h>
//-----Interface-----
#interface Person: NSObject{
int age;
int weight;
NSString *name;
}
-(void) print;
-(void) setAge: (int) a;
-(void) setWeight: (int) w;
-(void) setName: (NSString*) n;
#end
//-----Implementation-----
#implementation Person
-(void) print{
NSLog(#"%# is %i years old and my weight is %i pounds", name, age, weight);
}
-(void) setAge: (int) a{
age=a;
}
-(void) setWeight: (int) w{
weight=w;
}
-(void) setName: (NSString*) n{
name=n;
}
#end
//-----Main Program-----
int main(int argc, const char * argv[]) {
#autoreleasepool {
Person *james = [[Person alloc]init];
Person *bob = [[Person alloc]init];
[james setAge: 55];
[james setWeight: 400];
[james print];
[bob setAge: 80];
[bob setWeight: 150];
[bob print];
}
return 0;
}
It should return "james is 55 years old and my weight is 400 pounds" and "bob is 80 years old and my weight is 150 pounds"
But instead of "bob" and "james" I am getting "(null)"
Any ideas of why this could be happening?
You're not actually calling setName anywhere in your code ;) Try:
// ... other code happens here, then:
#autoreleasepool {
Person *james = [[Person alloc]init];
Person *bob = [[Person alloc]init];
[james setAge: 55];
[james setWeight: 400];
[james setName: #"james"]; // you need this
[james print];
[bob setAge: 80];
[bob setWeight: 150];
[bob setName: #"bob"]; // and this
[bob print];
}
In the end, bear in mind that just because you created a class instance with a particular name (in this case james and bob), doesn't explicitly set a property such as name.
You might try something a little clever like adding an initialization method to inside your class:
In your header/interface:
- (id) initWithName:(NSString*)name;
And in your implementation:
- (id) initWithName:(NSString*)name
{
self = [super init];
if (self != nil)
{
[self setName:name];
}
return self;
}
Then you can call:
Person *james = [[Person alloc]initWithName:#"james"];
it seems you never call something like [james setName:#"james"] so name property is never initialised
Why it says that numerator and denominator in the category MathOps is undeclared variable ?
It is in the Chapter 11 and the Program 11.1
Can't understand why it doesn't work, because it is the same code as in the book without any mistakes.
Please help
Code:
#import <Foundation/Foundation.h>
#import "complex.h"
#import "Fraction.h"
#import "XYPoint.h"
#interface Fraction (MathOps)
-(Fraction *)add:(Fraction *) f;
-(Fraction *)mul:(Fraction *) f;
-(Fraction *)sub:(Fraction *) f;
-(Fraction *)div:(Fraction *) f;
#end
#implementation Fraction (MathOps)
-(Fraction *)add:(Fraction *) f
{
Fraction *result = [[Fraction alloc]init];
result.numerator = (numerator * f.denominator)+(denominator * f.numerator);
// numerator and denominator: Using undeclared variables.
result.denominator = denominator * f.denominator;
}
-(Fraction *)mul:(Fraction *) f
{
Fraction *result = [[Fraction alloc]init];
result.numerator = numerator * f.numerator;
result.denominator = denominator * f.denominator;
// numerator and denominator: Using undeclared variables.
}
-(Fraction *)sub:(Fraction *) f {}
-(Fraction *)div:(Fraction *) f {}
#end
typedef Fraction *FractionObj;
int main (int argc, const char * argv[])
{
#autoreleasepool {
complex *imaginary= [[complex alloc]init];
complex *real = [[complex alloc]init];
complex *results;
[real setReal:1];
[real setImaginary:2];
[real print];
[imaginary setReal:2];
[imaginary setImaginary:1];
[imaginary print];
results = [real add: imaginary];
[results print];
NSLog(#"FRACTIONS!");
Fraction *a = [[Fraction alloc]init];
Fraction *b = [[Fraction alloc]init];
id resultFraction;
[a setTo:20 over:3];
[b setTo:1 over:3];
[b minusSign];
[a minusSign];
id ab = a;
id ba = b;
[ab print: 0];
NSLog(#"-");
[ba print: 0];
NSLog(#"=");
resultFraction = [ab multiplyN: ba];
[resultFraction print: 1];
XYPoint *xy = [[XYPoint alloc]init];
[xy setX:100 andY:110];
[xy print];
NSLog(#"VERIFYING \n \n \n");
Fraction *fraction = [[Fraction alloc]init];
complex *Complex = [[complex alloc]init];
id number = [[complex alloc]init];
if([fraction isMemberOfClass: [complex class]])
NSLog(#"Fraction is member of class complex");
if([Complex isMemberOfClass: [NSObject class]])
NSLog(#"complex is member of class NSObject");
if([Complex isKindOfClass: [NSObject class]])
NSLog(#"complex is kind of class NSObject");
if([fraction isKindOfClass: [Fraction class]])
NSLog(#"Fraction is kind of class Fraction");
if([fraction respondsToSelector: #selector(print)])
NSLog(#"Fraction respond to selector print");
if([Complex respondsToSelector: #selector(print)])
NSLog(#"Complex responds to print");
if([Fraction instancesRespondToSelector: #selector(print)])
NSLog(#"Fraction's instances respond to print");
if([number respondsToSelector: #selector (print)])
NSLog(#"number responds to print");
if([number isKindOfClass: [complex class]])
NSLog(#"number is kind of class complex");
if([[number class] respondsToSelector:#selector (alloc)])
NSLog(#"Number class responds to alloc");
if([a counter]!=1){ NSLog(#"%i times was invoked method multiplyN", a.counter); }
else { NSLog(#"Only %i time was invoked method multiplyN", a.counter);}
typedef enum {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday} Day;
}
return 0;
}
Fraction.h:
#interface Fraction : NSObject
#property int numerator, denominator, counter;
//methods
#end
Fraction.m
#implementation
#synthesize numerator, denominator, counter;
//methods
#end
you might want to check your Fraction class file .h, check if you have a set property of numerator and denominator there.
#property(nonatomic, ...) Type *numerator
#property(nonatomic, ...) Type *denominator
and also in your .m file, there should be
#synthesize numerator, denominator
or , in your xcode, point your mouse to that numerator or denominator while holding Command key then click the variable, xcode will take you to the file where the variable is declared, if its not declared, nothing will happen.
Try adding a self. prefix to your code:
result.numerator = (self.numerator * f.denominator)+(self.denominator * f.numerator);
It looks like you're using numerator and denominator without any previous setup of the variables. You may be confused by the fact that these variables have the same names as other variables, but if they aren't associated with the file they're being called from then your program won't recognize them. Your synthesize statement probably needs to be moved to underneath your #implementation statement. I'm somewhat confused by the fact that the code you're showing contains no declaration of numerator and denominator, and I'm sure that your compiler is too.
I m pretty new to objective-c, and trying some examples on my own. Here is my sample code
#import <objc/objc.h>
#import <Foundation/Foundation.h>
#interface Test:NSObject
{
int noOfWheels;
int total;
}
#property int noOfWheels;
#property int total;
-(void) print;
#end
#implementation Test
#synthesize noOfWheels, total;
-(void) print
{
NSLog (#" noofWheels is %i, total %i ", noOfWheels, total);
}
#end
int main ( int argc, char ** argv)
{
Test *t = [Test alloc];
t = [t init];
[t setnoOfWheels: 10];
[t settotal: 300];
[t print];
}
and it compiled with no error, but when i run the program i get the following error.
Uncaught exception NSInvalidArgumentException, reason: -[Test setnoOfWheels:]: unrecognized selector sent to instance 0x87aef48
What am i doing wrong in my code ?
By default 1st letter of iVar is capitalized in setter method name. So correct call will be:
[t setNoOfWheels: 10];
[t setnoOfWheels: 10];
should be
[t setNoOfWheels: 10];
or even better, since you're declaring a property:
t.noOfWheels = 10;
I'm learning Objective-C and just trying out some sample code. I am getting the following error message:
unrecognized selector sent to class
Here is my code.
Basics.m
#import <Foundation/Foundation.h>
#import "Fraction.h"
int main (int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Fraction *myFraction;
// Create an instance of a Fraction
myFraction = [Fraction alloc];
myFraction = [Fraction init];
// set Fraction to 1/3
[myFraction setNumerator: 1];
[myFraction setDenominator: 3];
// Display the value using the print method
NSLog(#"The value of myFraction is:");
[myFraction print];
[myFraction release];
[pool drain];
return 0;
}
Fraction.h
#import <Foundation/Foundation.h>
// -- interface section --//
#interface Fraction : NSObject {
int numerator;
int denominator;
}
// public method signatures
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
#end
Fraction.m
//--implementation section --//
#implementation Fraction
-(void) print
{
NSLog(#"%i/%i",numerator,denominator);
}
-(void) setNumerator: (int) n
{
numerator = n;
}
-(void) setDenominator: (int) d
{
denominator = d;
}
#end
alloc is a class method, but init is an instance method. In your code, the compiler is complaining that it can't find any class method named init, which is accurate. To correct this, you should call init upon the instance you received back from alloc, like so:
myFraction = [Fraction alloc];
myFraction = [myFraction init];
but the most common pattern is to nest the calls like this:
// calls -init on the object returned by +alloc
myFraction = [[Fraction alloc] init];
This also helps you avoid errors that might occur by calling methods on an object that has been allocated, but not yet initialized.
In addition to what has been said regarding the nested alloc / init call, something you may be interested in is description. In your Fraction class implementation, add a method like this:
- (NSString *) description
{
return [NSString stringWithFormat:#"%i/%i", numerator, denominator];
}
Now, you can use it directly in NSLog statements like this:
// set Fraction to 1/3
[myFraction setNumerator: 1];
[myFraction setDenominator: 3];
// Display the value using the print method
NSLog(#"The value of myFraction is: %#", myFraction);
I know this answer was awhile ago so I wanted to give a little update. If you are using alloc/init to initialize you can shorten it to just
[Fraction new]
and that will be equivalent.
i am writing my first custom class in objective-c and when i am trying to implement an instance of my custom class i get warnings that say "car may not respond to '+alloc'" and "car may not respond to '+init'" and if i use new instead i get the same warning that it may not respond to new. does anyone know why this might be? here is my code:
#import <Foundation/Foundation.h>
#interface Car
{
NSString *color;
NSString *make;
int year;
}
- (void) print;
- (void) setColor: (NSString *) c;
- (void) setMake: (NSString *) m;
- (void) setYear: (int) y;
#end
#implementation Car
- (void) print
{
NSLog(#"The $d Ford %# is $#.", year, make, color);
}
- (void) setColor: (NSString *) c
{
color=c;
}
- (void) setMake: (NSString *) m
{
make=m;
}
- (void) setYear: (int) y
{
year=y;
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Car *car;
car = [Car alloc];
car = [Car init];
[car setColor:#"blue"];
[car setMake:#"Bronco"];
[car setYear:1992];
[car print];
[car release];
[pool drain];
return 0;
}
Looks like you have two problems; one, you should probably explicitly subclass NSObject. Two, you aren't calling init on the allocated memory... try the following changes:
#interface Car : NSObject
Car *car = [[Car alloc] init];
You should also look into using properties for your "setColor", "setMake", etc. because you aren't retaining or releasing those strings properly, and they will leak and cause an ugly mess. It really helped me to turn on the static analyzer (you can set this in the project settings, or press Apple-Shift-A to build with the analyzer enabled).
EDIT:
OK, so the accepted "answer" post has memory issues... and it doesn't look like it's going to get fixed, so here is the whole thing... properly done:
#import <Foundation/NSObject.h>
#import <Foundation/Foundation.h>
#interface Car : NSObject
{
NSString *color;
NSString *make;
int year;
}
#property (retain,readwrite) NSString * color;
#property (retain,readwrite) NSString * make;
#property (assign,readwrite) int year;
- (void) print;
#end
#implementation Car
#synthesize color;
#synthesize make;
#synthesize year;
- (void) print
{
NSLog(#"The %d Ford %# is %#.", year, make, color);
}
- (void) dealloc
{
if (color)
[color release];
if (make)
[make release];
[super dealloc];
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Car *car = [[Car alloc] init];
car.color = #"blue";
car.make = #"Bronco";
car.year = 1992;
[car print];
[car release];
[pool drain];
return 0;
}
If you want to see the PROBLEM with the accepted answer, try this modified main function (using the rest of his post):
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Car *car = [[Car alloc] init];
// Let's pretend we are getting a string from somewhere else:
NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardInput];
NSData *inputData;
NSString *inputString;
printf("Type the color: ");
inputData = [fileHandle availableData];
inputString = [[NSString alloc] initWithData: inputData encoding:NSUTF8StringEncoding];
[car setColor:inputString];
[car setMake:#"Bronco"];
[car setYear:1992];
// This works:
[car print];
// But now, the place that gave us the string releases it:
[inputString release];
// UT OH! Danger Will Robinson!
[car print];
[car release];
[pool drain];
return 0;
}
You can use the exact same main method with my posted code, and it will work without an error because the Car class will retain the string, and release it when it's done. (and the setXXX: is also valid when using properties)
EDIT: Compiler outsmarted me when I tried to demo the EXEC_BAD_ACCESS using a static string... ha.
First of all, your Car-class should inherit from NSObject (thats the reason why the +alloc method isnt found)
#interface Car : NSObject
{
NSString *color;
NSString *make;
int year;
}
(void) print;
(void) setColor: (NSString *) c;
(void) setMake: (NSString *) m;
(void) setYear: (int) y;
#end
The "init" method is an instance-method that meens you can only send that message to an object not to a class (Car). The normal way is to send the +alloc message to the class to instanciate an object of that class. then you send this created object the -init message:
Car *car;
car = [Car alloc];
car = [car init];
Or the most convenient way:
car = [[Car alloc] init];
The alloc method creates the object and reserves the memory for it, for that its a CLASS-method because there is no object yet. the init message is then send to the created object.