2010-06-27 1 views
0

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

Приложение хранит файл в папке «Документы» ОК, и проверка структуры файла, похоже, содержит данные, которые я ожидал бы. Однако, когда файл загружается в Unarchiver возвращает ошибку

*** Нагрузочный приложение из-за неперехваченного исключением 'NSInvalidUnarchiveOperationException', причина: *** - [NSKeyedUnarchiver decodeObjectForKey]: Unarchiver закончил; не может расшифровать ничего больше '

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

Код:

App Делегат:

интерфейс:

#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

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

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

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

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

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

// Decoding: 
appData = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
+0

Спасибо Оле, не знаю, сколько раз я прочитал этот код и пропустил что-то совершенно очевидное. –

+0

И я все для упрощения, спасибо за подсказку. –