Help please! my first program in objective c. Followed a tutorial word for word but it gives me this error that I don’t know quite how to read for objective c.
SimpleCar.h:
#import <Cocoa/Cocoa.h>
@interface SimpleCar : NSObject {
NSString* make;
NSString* model;
NSNumber* vin;
}
// set methods
- (void) setVin: (NSNumber*)newVin;
- (void) setMake: (NSString*)newMake;
- (void) setModel: (NSString*)newModel;
// convenience method
- (void) setMake: (NSString*)newMake
andModel: (NSString*)newModel;
// get methods
- (NSString*) make;
- (NSString*) model;
- (NSNumber*) vin;
@end
SimpleCar.m:
#import "SimpleCar.h"
@implementation SimpleCar
// set methods
- (void) setVin: (NSNumber*)newVin {
[vin release];
vin = [[NSNumber alloc] init];
vin = newVin;
}
- (void) setMake: (NSString*)newMake {
[make release];
make = [[NSString alloc] initWithString:newMake];
}
- (void) setModel: (NSString*)newModel {
[model release];
model = [[NSString alloc] initWithString:newModel];
}
// convenience method
- (void) setMake: (NSString*)newMake
andModel: (NSString*)newModel {
// Reuse our methods from earlier
[self setMake:newMake];
[self setModel:newModel];
}
- (NSString*) make {
return make;
}
- (NSString*) model {
return model;
}
- (NSNumber*) vin {
return vin;
}
-(void) dealloc
{
[vin release];
[make release];
[model release];
[super dealloc];
}
@end
CarApp.m:
#import <Foundation/Foundation.h>
#import "SimpleCar.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SimpleCar *myCar = [[SimpleCar alloc] init];
NSNumber *newVin = [NSNumber numberWithInt:123];
[myCar setVin:newVin];
[myCar setMake:@"Honda" andModel:@"Civic"];
NSLog(@"The car is: %@ %@", [myCar make], [myCar model]);
NSLog(@"The vin is: %@", [myCar vin]);
[myCar release];
[pool drain];
return 0;
}
compiler call:
bash-3.2$ gcc CarApp.m SimpleCar.m -g -m64
error:
Undefined symbols for architecture x86_64:
"___CFConstantStringClassReference", referenced from:
CFString in ccR0Zlgm.o
CFString in ccR0Zlgm.o
CFString in ccR0Zlgm.o
CFString in ccR0Zlgm.o
"_objc_msgSend", referenced from:
_main in ccR0Zlgm.o
-[SimpleCar setVin:] in ccJfVliU.o
-[SimpleCar setMake:] in ccJfVliU.o
-[SimpleCar setModel:] in ccJfVliU.o
-[SimpleCar setMake:andModel:] in ccJfVliU.o
(maybe you meant: l_objc_msgSend_fixup_release, l_objc_msgSend_fixup_alloc )
"_NSLog", referenced from:
_main in ccR0Zlgm.o
"_objc_msgSend_fixup", referenced from:
l_objc_msgSend_fixup_alloc in ccR0Zlgm.o
l_objc_msgSend_fixup_release in ccR0Zlgm.o
l_objc_msgSend_fixup_release in ccJfVliU.o
l_objc_msgSend_fixup_alloc in ccJfVliU.o
(maybe you meant: l_objc_msgSend_fixup_release, l_objc_msgSend_fixup_alloc )
"_OBJC_CLASS_$_NSAutoreleasePool", referenced from:
objc-class-ref in ccR0Zlgm.o
"_OBJC_CLASS_$_NSNumber", referenced from:
objc-class-ref in ccR0Zlgm.o
objc-class-ref in ccJfVliU.o
"_objc_msgSendSuper2", referenced from:
-[SimpleCar dealloc] in ccJfVliU.o
"_OBJC_METACLASS_$_NSObject", referenced from:
_OBJC_METACLASS_$_SimpleCar in ccJfVliU.o
"__objc_empty_cache", referenced from:
_OBJC_METACLASS_$_SimpleCar in ccJfVliU.o
_OBJC_CLASS_$_SimpleCar in ccJfVliU.o
"__objc_empty_vtable", referenced from:
_OBJC_METACLASS_$_SimpleCar in ccJfVliU.o
_OBJC_CLASS_$_SimpleCar in ccJfVliU.o
"_OBJC_CLASS_$_NSObject", referenced from:
_OBJC_CLASS_$_SimpleCar in ccJfVliU.o
"_OBJC_CLASS_$_NSString", referenced from:
objc-class-ref in ccJfVliU.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
It looks like you just created an Xcode Workspace without an Xcode project. Here’s a project that you could use:
http://www.markdouma.com/developer/CarApp.zip
Generally, you just choose File > New Project to create a new project. You’d likely want a Foundation-based command-line program for this particular project.
Unfortunately, the tutorial didn’t give the best implementation of the
SimpleCarclass. Below is one possible rewrite:The commented code above is the original code. It is both potentially dangerous and also leaks memory. The first line of the original code releases
vinbefore doing anything else, which is potentially dangerous. For example, what if in yourCarApp.myou did this:The original code would have released the existing
vinvalue without bothering to make sure the value being passed in wasn’t actuallyvinitself. By settingvin = newVin, it was settingvinto point to itself but after being released. Any subsequent attempts to send messages tovinwould result in a crash or unpredictable results.The original code also leaks memory. Instances of
NSNumberare immutable, so creating a number throughalloc/initdoesn’t really make much sense (since it will always be zero, and can never be changed). My replacement code first retains the value that is passed in, in case it happens to bevin. It then releasesvinand then assignsvintonewVin.The
setMake:andsetModel:methods are problematic for the same reasons.