Файл NSKeyedArchiver - потеря данных - PullRequest
3 голосов
/ 28 января 2010

Использование Iphone SDK 3.1.2. Я сохраняю некоторую информацию в файл, используя NSKeyedArchiver объект. У меня есть 4 ключа. Я читаю данные из файла для всех 4 ключей на applicationDidFinshLaunching и записываю обратно в файл (все 4 ключа) на applicationDidTerminate. Кроме того, когда пользователь сохраняет любую информацию, я записываю данные для конкретного ключа, для которого он.

Если изначально нет файла, я выделяю массив для списка учетных записей, это позволяет мне добавлять к нему учетные записи.

У меня проблемы с файлом, периодически теряющим сохраненные в нем данные. Иногда это влияет на один ключ, т. Е. На список учетных записей, иногда это список избранных. Кажется, это усугубляется, если я просто сохраняю 1 ключ в отличие от всех 4. Я просмотрел файл, используя Organier и действительно, данные отсутствуют. Дело в том, что много раз это не работает. Я не знаю, почему это так противоречиво. Также, если я прерву отладчик в xcode, я буду ожидать потерю только недавних изменений, а не целых данных файлов, которые, кажется, происходят. Вся эта история с NSKeyedArchiv кажется настолько ненадежной, что я обдумываю, возможно, другую постоянную стратегию хранения. Кто-нибудь сталкивался с чем-нибудь подобным.

- (void)viewDidLoad 
{

if( self.accountList == nil)
{
    NSMutableArray *array = [[NSMutableArray alloc] init];
    self.accountList = array;
    [array release];
}

if( self.phoneSettings == nil)
{
 PhoneSettings* mySettings = [[PhoneSettings alloc] initSettings];
 self.phoneSettings = mySettings;
 [mySettings release];
}



 NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
    NSData *data = [[NSMutableData alloc]
                    initWithContentsOfFile:[self dataFilePath]];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] 
                                     initForReadingWithData:data];
    NSMutableArray *archiveArray = [unarchiver decodeObjectForKey:kDataKey];
 if(archiveArray != nil)
  self.accountList = [archiveArray retain];
 else
  LOG("No archived accounts" ); 

 NSMutableArray *archiveCallList = [unarchiver decodeObjectForKey:kCallListKey];
  if(archiveCallList !=nil)
    appDelegate.callList = [archiveCallList retain];

  NSMutableArray *archiveFavouritesList = [unarchiver   decodeObjectForKey:kfavouritesKey];
  if(archiveFavouritesList != nil)
   appDelegate.favouritesList = [archiveFavouritesList retain];

  PhoneSettings* archiveSettings = [unarchiver decodeObjectForKey:kPhoneSettings];
  if (archiveSettings != nil)
   self.phoneSettings = [archiveSettings retain];

    [unarchiver finishDecoding];          
    [unarchiver release];
    [data release];
}

затем в

- (void)applicationWillTerminate:(NSNotification *)notification {

 LOG("Application terminating");
 SessionTalkAppDelegate* appDelegate = (SessionTalkAppDelegate*)[[UIApplication sharedApplication] delegate];




NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]
                             initForWritingWithMutableData:data];
[archiver encodeObject:self.accountList forKey:kDataKey];
 [archiver encodeObject:appDelegate.callList forKey:kCallListKey];
 [archiver encodeObject:appDelegate.favouritesList forKey:kfavouritesKey];
 [archiver encodeObject:self.phoneSettings forKey:kPhoneSettings];
[archiver finishEncoding];

[data writeToFile:[self dataFilePath] atomically:YES];
   [archiver release];
[data release];    
}

1 Ответ

4 голосов
/ 28 января 2010

Вам не нужно столько кода. Сохраните ваши данные:

NSMutableDictionary *appState = [NSMutableDictionary dictionary];
[appState setObject: self.accountList forKey: kDataKey];
[appState setObject: appDelegate.callList forKey: kCallListKey];
[appState setObject: self.phoneSettings forKey: kPhoneSettings];
if ( [NSKeyedArchiver archiveRootObject: appState toFile: [self dataFilePath]] == NO )
    NSLog(@"Failed to archive %@", appState);

Считать данные:

NSMutableDictionary *appState = [NSKeyedUnarchiver unarchiveObjectWithFile: [self dataFilePath]];

Обратите внимание, что NSKeyedUnarchiver может вызвать NSInvalidArgumentException, если файл не содержит действительный архив, поэтому вы должны заключить вызов в блок @try {}.

...