#xcode #memory-management #nskeyedarchiver #nscoding #saving-data
#xcode #управление памятью #nskeyedarchiver #nscoding #сохранение данных
Вопрос:
У меня есть пользовательский класс, который я хочу сохранить и загрузить. Класс содержит NSDate, NSString и NSNumber. Я внедрил протокол NSCoding в файл .h. Вот код, который у меня есть на данный момент. Дата — это NSDate. Имя — это NSString. HomeAway — это номер NSNumber.
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:theDate forKey:@"theDate"];
[aCoder encodeObject:theName forKey:@"theName"];
[aCoder encodeObject:homeAway forKey:@"homeAway"];
}
-(id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super init])) {
theDate = [aDecoder decodeObjectForKey:@"theDate"];
theName = [aDecoder decodeObjectForKey:@"theName"];
homeAway = [aDecoder decodeObjectForKey:@"homeAway"];
}
return self;
}
Я использую приведенный ниже код для загрузки моего пользовательского объекта. Когда я использую print-object в отладчике, только HomeAway отображается как реальный объект. Дата и имя говорят, что 0x4e4f150, похоже, не указывают на допустимый объект.
[gamesArray setArray:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];
Game *loadedGame = [gamesArray objectAtIndex:gameNumber];
Я сохраняю данные, используя следующий код:
Я использую это, чтобы вызвать свой класс для создания новой игры (пользовательский класс, который я пытаюсь сохранить). Код до NSDate *aDate = [Дата игрового процесса]; не имеет значения.
-(void)newGame {
if (homeAway != 0) {
if (dateChanged == 1) {
if ([nameField.text length] > 0) {
[homeButton setImage:[UIImage imageNamed:@"HomeGray.png"] forState:UIControlStateNormal];
[awayButton setImage:[UIImage imageNamed:@"AwayGray.png"] forState:UIControlStateNormal];
[dateButton setImage:[UIImage imageNamed:@"DateGray.png"] forState:UIControlStateNormal];
[nameField setBackground:[UIImage imageNamed:@"textField.png"]];
NSDate *aDate = [gameDate date];
NSString *aString = [[[NSString alloc] initWithString:[nameField text]] autorelease];
UIApplication *app = [UIApplication sharedApplication];
[[[(miShotTrackAppDelegate *)[app delegate] viewController] courtViewOne] newGame:aDate withName:aString andPlace:homeAway];
[loadTable reloadData];
datePicke = 0;
homeAway = 0;
dateChanged = 0;
nameField.text = @"";
[self goBack];
[self autoSave];
}
}
}
}
Из этого метода я вызываю метод NewGame, который
-(void)newGame:(NSDate *)theDate withName:(NSString *)theName andPlace:(int)homeAway {
Game *newGame = [[Game alloc] init];
NSDate *tDate = [NSDate new];
tDate = theDate;
[newGame setTheDate:tDate];
NSString *tString = [NSString stringWithString:theName];
[newGame setTheName:tString];
NSNumber *theNumber = [NSNumber numberWithInt:homeAway];
[newGame setHomeAway:theNumber];
[gamesArray addObject:newGame];
gameNumber = [gamesArray count] - 1;
NSString *path = [self findGamesPath];
[NSKeyedArchiver archiveRootObject:gamesArray toFile:path];
[newGame release];
}
Почему мои объекты не сохраняются? Имеет ли к этому какое-то отношение копирование моих объектов? Я действительно получаю сообщение об ошибке в строке с комментариями, в которой говорится «исключение неправильного доступа». Пожалуйста, помогите…
Ответ №1:
Вы неправильно реализуете -initWithCoder. -decodeObjectForKey возвращает автоматически выпущенный объект. Итак, то, как вы написали метод, в итоге приводит к появлению висячих указателей на все ваши игровые ивары. Измените initWithCoder на:
-(id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super init])) {
[self setTheDate:[aDecoder decodeObjectForKey:@"theDate"]];
[self setTheName:[aDecoder decodeObjectForKey:@"theName"]];
[self setHomeAway:[aDecoder decodeObjectForKey:@"homeAway"]];
}
return self;
}
и это должно сработать у вас.
Комментарии:
1. Спасибо вам за это! Я должен добавить к этому сообщению: не забудьте также вызвать супер функции! Если вы этого не сделаете, вы получите странные результаты. Итак:
if ((self = [super initWithCoder:aDecoder])) {
в приведенном выше примере.