Похоже, вы только что создали рабочее пространство Xcode без проекта Xcode. Вот проект, который вы могли бы использовать:
http://www.markdouma.com/developer/CarApp.zip
Как правило, вы просто выбираете Файл> Новый проект, чтобы создать новый проект. Скорее всего, вам понадобится программа командной строки на основе Foundation для этого конкретного проекта.
К сожалению, учебник не дал лучшую реализацию класса SimpleCar
. Ниже приведен один из возможных вариантов:
#import "SimpleCar.h"
@implementation SimpleCar
-(void) dealloc
{
[vin release];
[make release];
[model release];
[super dealloc];
}
// set methods
- (void) setVin: (NSNumber*)newVin {
[newVin retain];
[vin release];
vin = newVin;
// [vin release];
// vin = [[NSNumber alloc] init];
// vin = newVin;
}
Код с комментариями выше - это оригинальный код. Это и потенциально опасно, и также приводит к утечке памяти. Первая строка исходного кода выпускает vin
, прежде чем делать что-либо еще, что потенциально опасно. Например, что если в вашем CarApp.m
вы сделали это:
NSNumber *vinValue = [car vin];
[car setVin:vin];
NSLog(@"car's vin == %@", [car vin]); // unpredictable results/crash
Исходный код освободил бы существующее значение vin
, не заботясь о том, чтобы передаваемое значение на самом деле не было vin
. Установив vin = newVin
, он установил vin
, чтобы он указывал на себя, но после освобождения. Любые последующие попытки отправить сообщения на vin
могут привести к сбою или непредсказуемым результатам.
Исходный код также приводит к утечке памяти. Экземпляры NSNumber
являются неизменяемыми, поэтому создание числа через alloc/init
не имеет особого смысла (поскольку оно всегда будет нулевым и никогда не может быть изменено). Мой код замены сначала сохраняет переданное значение, в случае, если оно окажется vin
. Затем он освобождает vin
, а затем присваивает vin
newVin
.
Методы setMake:
и setModel:
проблематичны по тем же причинам.
- (void) setMake: (NSString*)newMake {
[newMake retain];
[make release];
make = newMake;
// [make release];
// make = [[NSString alloc] initWithString:newMake];
}
- (void) setModel: (NSString*)newModel {
[newModel retain];
[model release];
model = 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;
}
@end