0

我正在编写一个 iPhone 应用程序,但在尝试存档设置时遇到了问题。我正在使用一个类 (AppData) 来保存设置(该示例目前仅显示一个),并使用 App Delegate 在应用加载时创建 AppData 的实例,并在应用终止时存储它。我符合(我认为)NSCoding 协议

该应用程序将文件存储在 Documents 目录中,并且检查文件结构似乎包含我期望的数据。但是,当文件在 unarchiver 中加载时返回错误

***由于未捕获的异常“NSInvalidUnarchiveOperationException”而终止应用程序,原因:***-[NSKeyedUnarchiver decodeObjectForKey:]:unarchiver 已完成;无法再解码任何东西'

我一直在努力解决这个问题,所以如果有人能看到这个问题,我将非常感激。

代码:

应用代表:

界面:

#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

应用数据类:

界面:

#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

最后是常量.h

//此文件包含所有应用程序常量

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

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

1 回答 1

1

正如错误消息所述,您finishDecoding在完成解码之前正在调用。然后你再次调用它:

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

那是行不通的。

也就是说,您的代码比它需要的更复杂。为什么不这样:

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

// Decoding:
appData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
于 2010-06-27T10:05:19.223 回答