2010-06-27 40 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