objective-c synthesizeing leads to error? - objective-c

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;

Related

How does the Xcode breakpoint system interact with memory management?

Here's a little experiment:
#interface Model : NSObject
#property (copy) NSString *value;
-(instancetype)initWith:(NSString *)value;
#end
#implementation Model
-(instancetype)initWith:(NSString *)value {
self = [super init];
self.value = value;
return self;
}
#end
#import <Foundation/Foundation.h>
#import "Model.h"
void experiment(Model *m);
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Model *ma = [[Model alloc] initWith:[[NSUUID UUID] UUIDString]];
experiment(ma);
NSLog(#"yyy %#", [ma value]);
}
return 0;
}
void experiment(ModelA *m) {
NSString *testValue = nil;
testValue = [m value];
NSLog(#"xxx %#", testValue);
}
When run, this produces the following:
Hello, World!
xxx 6005A7B0-F71C-4755-B1BF-792D6296B716
yyy 6005A7B0-F71C-4755-B1BF-792D6296B716
Program ended with exit code: 0
But suppose I make this line:
testValue = [m value];
part of a breakpoint:
And this changes everything:
Hello, World!
(__NSCFString *) $0 = 0x000000010071e220 #"1C0DCB39-BFBB-4E67-A041-E6B58615BDFD"
xxx 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
yyy 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
*** -[CFString release]: message sent to deallocated instance 0x10071e220
And a crash. I see what's happening--the string is released once we exit the function scope, and the second time when the Model object is destroyed, which is an overrelease. But why doesn't the breakpoint (or more precisely, the lldb expression inside the breakpoint) handle the reference count correctly?

Objective-C - Mac NSLog not working

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 ];

objectiveC autorelease issue, what is wrong with code?

New to objective-C,
#import <objc/objc.h>
#import <Foundation/Foundation.h>
#interface Test:NSObject
{
int x,y, abc;
NSString *v1, *v2;
}
#property int x , y, abc;
-(void) print;
#end
#implementation Test
#synthesize x,y, abc;
-(void) print
{
NSLog (#"v1 and v2 values %i, %i ", v1, v2);
}
#end
int main ( int argc, char **argv)
{
Test *t = [[Test alloc] init];
/* Synthesized Set Method */
[t setX:100];
[t setY:200];
/* Synthesized Get Method */
NSLog (#"Retrieving Values %i, %i ",[t x], [t y]);
/* another Way to retrieve the throuhg KVC Model */
NSLog (#" KVC Retrieveal %i ", [t valueForKey:#"x"]);
}
I did not get compile time error, but run time error i got :
2012-04-11 16:25:08.470 testpgm[22237] Retrieving Values 100, 200
2012-04-11 16:25:08.513 testpgm[22237] autorelease called without pool for object (0x8e78ca0) of class NSMethodSignature in thread <NSThread: 0x8e23a08>
2012-04-11 16:25:08.514 testpgm[22237] autorelease called without pool for object (0x8e94610) of class NSIntNumber in thread <NSThread: 0x8e23a08>
2012-04-11 16:25:08.514 testpgm[22237] KVC Retrieveal 149505552
Looks like it is something to do with memory issue. some one point out the issue ?
NOTE: With all your inputs, i could resolve the autorelease issue, but still
NSLog (#" KVC Retrieveal %i ", [t valueForKey:#"x"]);
does not print the proper value but the garbage. Am i doing something wrong?
When you are in the run loop of an application, there is a default autorelease pool created for you. However, when you are running with your own main, you need to create an autorelease pool manually at the top of your main, and drain it periodically.
NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
// Your code that uses autorelease...
[myPool drain];
If you are compiling with the new LLVM compiler, use the new #autoreleasepool feature instead.
The main routine does not create an autorelease pool.
Use one of these methods depending on the version and compiler you are using.
Newer or with ARC:
int main(int argc, char *argv[])
{
#autoreleasepool {
// your code
}
}
or
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your code
[pool drain];
}
The code has numerous other problems such as:
NSLog (#"v1 and v2 values %i, %i ", v1, v2);
which should be
NSLog (#"v1 and v2 values %#, %# ", v1, v2);
%# is used to print objects, %i for integers.
The line:
NSLog (#" KVC Retrieveal %i ", [t valueForKey:#"x"]);
is interesting because valueForKey returns an object (in this case an NSNumber) so the correct statement is:
NSLog (#" KVC Retrieveal %# ", [t valueForKey:#"x"]);
Running the program with these corrections produces:
Retrieving Values 100, 200
KVC Retrieveal 100
main function must have an autorelease pool.
int main(int argc, char *argv[])
{
#autoreleasepool {
// you code
return ...;
}
}
EDIT:
Regarding your second part of question. valueForKey returns id, cast it to int
NSLog (#" KVC Retrieveal %i ", [[t valueForKey:#"x"] intValue]);
int main ( int argc, char **argv)
{
NSAutoreleasePool *myPool = [NSAutoreleasePool new];
Test *t = [[Test alloc] init];
/* Synthesized Set Method */
[t setX:100];
[t setY:200];
/* Synthesized Get Method */
NSLog (#"Retrieving Values %i, %i ",[t x], [t y]);
/* another Way to retrieve the throuhg KVC Model */
NSLog (#" KVC Retrieveal %i ", [t valueForKey:#"x"]);
[pool drain];
}
may be it will work

Unrecognized selector sent to class

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.

ignoring messages in objective C

I have some obj-c code, i plan to send unsupport messages in plugin. However i cant seem to ignore messages. I thought "-(id) forward: (SEL) selector: (marg_list) arglist;" would solve it but it hasnt. How do i have this app run entirely without getting a warning and a termination call?
#import <stdio.h>
#import <objc/Object.h>
//------- #interface section -------
#interface Fraction: Object
{
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(id) forward: (SEL) selector: (marg_list) arglist;
#end
//------- #implementation section -------
#implementation Fraction;
-(void) print
{
printf (" %i/%i ", numerator, denominator);
}
-(void) setNumerator: (int) n
{
numerator = n;
}
-(void) setDenominator: (int) d
{
denominator = d;
}
-(id) forward: (SEL) selector: (marg_list) arglist
{
return nil;
}
#end
//------- program section -------
int main (int argc, char *argv[])
{
Fraction *myFraction;
// Create an instance of a Fraction
myFraction = [Fraction alloc];
myFraction = [myFraction init];
// Set fraction to 1/3
[myFraction setNumerator: 1];
[myFraction setDenominator: 3];
// Display the fraction using the print method
printf ("The value of myFraction is:");
[myFraction print];
printf ("\n");
[myFraction someMsg: 99];
[myFraction free];
printf("end");
return 0;
}
Rather than handing this in the plugin, it would be best to do it in the caller. Instead of:
[myFraction someMsg: 99];
you should check if myFraction responds to the someMsg selector:
if ([myFraction respondsToSelector:#selector(someMsg:)]) {
[myFraction someMsg: 99];
}
The -respondsToSelector: method is defined in the NSObject Protocol Reference, so note that your MyFraction object needs to inherit from NSObject, not Object (or else implement the NSObject protocol yourself). Of course, this is really best practice anyway -- directly subclassing the Object class is generally discouraged.