Ошибка при использовании NSKeyedUnarchiver - PullRequest
0 голосов
/ 27 июня 2010

Я пишу приложение для iPhone, и у меня возникают проблемы при попытке заархивировать настройки. Я использую класс (AppData) для хранения настроек (пример показывает только один в настоящее время) и использую делегат приложения для создания экземпляра AppData при загрузке приложения и сохранения его при завершении работы приложения. Я соответствую (я думаю) протоколу NSCoding

Приложение сохраняет файл в каталоге Documents, и проверка структуры файла, кажется, содержит данные, которые я ожидал. Однако при загрузке файла в unarchiver возвращает ошибку

*** Завершение приложения из-за необработанного исключения «NSInvalidUnarchiveOperationException», причина: *** - [NSKeyedUnarchiver decodeObjectForKey:]: разархивирование завершено; больше ничего не могу декодировать '

Я уже некоторое время борюсь с этим, поэтому, если кто-нибудь увидит проблему, я был бы очень благодарен.

Код:

Делегат приложения:

Интерфейс:

#import <UIKit/UIKit.h>
#import "AppData.h"
#import "Constants.h"

@interface iLeanAppDelegate : NSObject <UIApplicationDelegate> {
    AppData *appData;
    UIWindow *window;
    UITabBarController *tabBarController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) AppData *appData;

@end

реализация:

#import "iLeanAppDelegate.h"


@implementation iLeanAppDelegate

@synthesize window;
@synthesize tabBarController; 
@synthesize appData;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    appData = [[AppData alloc] init];
    if ([[NSFileManager defaultManager] fileExistsAtPath:[AppData dataFilePath]]) {         //If previous settings have been found retrieve and initialise
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[AppData dataFilePath]];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        [unarchiver finishDecoding];    
    appData = [unarchiver decodeObjectForKey:kDataKey];
        [unarchiver finishDecoding];

    [unarchiver release];
    [data release];
}

// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
}

-(void)applicationWillTerminate:(NSNotification *)notification {
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:appData forKey:kDataKey];
    [archiver finishEncoding];
    BOOL success = [data writeToFile:[AppData dataFilePath] atomically:YES];
    if (success)
        NSLog(@"OK");
    else
        NSLog(@"Problem here");
    [archiver release];
    [data release];

}

- (void)dealloc {
    [tabBarController release];
    [window release];
[appData release];
    [super dealloc];
}

@end

Класс AppData:

Интерфейс:

#import <Foundation/Foundation.h>
#import "Constants.h"

@interface AppData : NSObject <NSCoding, NSCopying> {

    BOOL audioAlert;        //YES = audio alerts are on, NO = audio alerts are off
}

+(NSString *)dataFilePath;

@property(nonatomic, assign) BOOL audioAlert;

@end

Реализация:

#import "AppData.h"


@implementation AppData

@synthesize audioAlert;


+(NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:kSettingsFilename];
}


#pragma mark NSCoding

-(void)encodeWithCoder:(NSCoder *)encoder {

    [encoder encodeBool:audioAlert forKey:kSettingsKey];
}

-(id)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        self.audioAlert = [decoder decodeObjectForKey:kSettingsKey];
    }

    return self;
}

#pragma mark -
#pragma mark NSCopying

-(id)copyWithZone:(NSZone *)zone {
    AppData *copy = [[[self class] allocWithZone: zone] init];
//Will do this once coding works
    return copy;
}

@end

Наконец-то constants.h

// Этот файл содержит все константы приложения

#define kSettingsFilename   @"archive"  //Filename where all application settings are stored

#define kSettingsKey        @"settingsKey"      //Key name
#define kDataKey            @"data"

1 Ответ

1 голос
/ 27 июня 2010

Как и в сообщении об ошибке, вы звоните finishDecoding до того, как закончите декодирование.И затем вы вызываете его снова:

[unarchiver finishDecoding];    
appData = [unarchiver decodeObjectForKey:kDataKey];
[unarchiver finishDecoding];

Это не может работать.

Тем не менее, ваш код сложнее, чем должен быть.Почему бы не это:

// Encoding:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:appData];

// Decoding:
appData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
...