2010-06-27 101 views
0

我正在写一个iPhone应用程序,并尝试存档设置时出现问题。我正在使用一个类(AppData)来保存设置(该示例目前只显示一个),并在应用程序加载时使用App Delegate创建AppData实例,并在应用程序终止时将其存储。我符合(我认为)的NSCoding协议错误使用NSKeyedUnarchiver

该应用程序将文件存储在文档目录中确定,并检查文件结构似乎持有我期望的数据。然而,当该文件中的取档加载返回错误

***终止应用程序由于未捕获的异常“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 

应用程序数据类:

接口:

#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

谢谢奥莱,不知道有多少次我读过这段代码,错过了一些非常明显的东西。 – 2010-06-27 20:19:02

+0

我只是为了简化,谢谢你的提示。 – 2010-06-27 20:21:30