私は iPhone アプリを書いていますが、設定をアーカイブしようとすると問題が発生します。クラス (AppData) を使用して設定を保持し (この例では現在 1 つだけを示しています)、App Delegate を使用して、アプリの読み込み時に AppData のインスタンスを作成し、アプリの終了時にそれを保存しています。私はNSCodingプロトコルに準拠しています(と思います)
アプリはファイルを Documents ディレクトリに保存し、ファイル構造を確認すると、期待どおりのデータが保持されているようです。ただし、ファイルがアンアーカイバーにロードされると、エラーが返されます
***
キャッチされていない例外 'NSInvalidUnarchiveOperationException' が原因でアプリを終了しています。理由:***
-[NSKeyedUnarchiver decodeObjectForKey:]: unarchiver has finished; これ以上は解読できません」
私はこれにしばらく取り組んでいるので、誰かが問題を見ることができれば、とても感謝しています.
コード:
アプリのデリゲート:
インターフェース:
#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"