zar*_*don 3 singleton objective-c nscoding nskeyedarchiver
我正在编写一个基本游戏,我使用的GameStateManager是一个单例并处理所有状态管理,例如保存,加载,删除方法.
我有一个单独的singelton处理所有的Game东西.游戏对象位于游戏状态管理器内部,因此我可以使用NSCoding和Archiving将其保存.
当我保存状态时,似乎没有问题,Game对象(单例)被正确保存.
但是,当我尝试加载状态(通过重新启动应用程序)时,游戏对象始终为null.
Strangley,如果我删除单例属性并使其成为标准类,这个问题就会消失,我可以加载类及其所有属性而不会出现任何重大问题.
总之,我这样做:
GameStateManager = Singleton,处理所有游戏状态管理(加载,保存)并具有游戏对象(游戏)
Game = Singleton,用于处理游戏中的事物并使用NSCoding协议.
用游戏对象保存游戏状态很好,对象显然就在那里.
加载游戏状态似乎使游戏对象为空.它应该存在,但由于某种原因它永远不会加载它.
如果我删除所有使游戏类成为singelton并使其成为正常类的属性,问题似乎就会消失.
我认为它与Game从未初始化的事实有关,但这没有意义,因为我可以在没有单例属性时加载游戏.
现在的代码如下.
// GameStateManager.m
-(void)saveGameState
{
CCLOG(@"METHOD: saveGameState()");
self.lastSaveDate = [NSDate date];
NSMutableData *data;
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:kGameSaveFile];
NSKeyedArchiver *archiver;
BOOL result;
data = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:self.lastSaveDate forKey:@"lastSaveDate"];
[archiver encodeObject:self.game forKey:@"game"];
[archiver finishEncoding];
result = [data writeToFile:archivePath atomically:YES];
[archiver release];
}
-(void)loadGameState
{
CCLOG(@"METHOD: loadGameState()");
NSData *data;
NSKeyedUnarchiver *unarchiver;
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:kGameSaveFile];
data = [NSData dataWithContentsOfFile:archivePath];
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// Customize unarchiver here
self.game = [unarchiver decodeObjectForKey:@"game"];
self.lastSaveDate = [unarchiver decodeObjectForKey:@"lastSaveDate"];
[unarchiver finishDecoding];
[unarchiver release];
CCLOG(@"Last Save Date = %@", self.lastSaveDate);
NSLog(@"game = %@", self.game);
}
// END OF GAMESTATEMANAGER
// -------------------------
// Game.h
@interface Game : NSObject
<NSCoding>
{
NSMutableArray *listOfCities;
NSMutableArray *listOfColors;
NSMutableArray *listOfPlayers;
}
@property (nonatomic, retain) NSMutableArray *listOfCities;
@property (nonatomic, retain) NSMutableArray *listOfColors;
@property (nonatomic, retain) NSMutableArray *listOfPlayers;
+(Game *) sharedGame;
//
// Game.m
// This is a cut-down version of the game object
// Game is a singelton
// The listOfCities, etc are arrays
//
@implementation Game
SYNTHESIZE_SINGLETON_FOR_CLASS(Game)
@synthesize listOfCities, listOfPlayers;
#pragma mark - NSCoding
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self)
{
self.listOfCities = [aDecoder decodeObjectForKey:@"listOfCities"];
self.listOfPlayers = [aDecoder decodeObjectForKey:@"listOfPlayers"];
NSLog(@"Cities = %d", [self.listOfCities count]);
NSLog(@"Players = %d", [self.listOfPlayers count]);
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
// Archive objects
NSLog(@"Cities = %d", [self.listOfCities count]);
NSLog(@"Players = %d", [self.listOfPlayers count]);
[aCoder encodeObject:self.listOfCities forKey:@"listOfCities"];
[aCoder encodeObject:self.listOfPlayers forKey:@"listOfPlayers"];
}
@end
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何使用NSCoding和Archiver成功保存和加载Objective C singelton?
编辑;
我试过了:
// In the GameStateManager
#pragma mark - NSCoding
-(id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.lastSaveDate = [[decoder decodeObjectForKey:@"lastSaveDate"] retain];
self.game = [[decoder decodeObjectForKey:@"game"] retain];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.lastSaveDate forKey:@"lastSaveDate"];
[encoder encodeObject:self.game forKey:@"game"];
}
Run Code Online (Sandbox Code Playgroud)
和
// In Game.m
self.listOfCities = [[aDecoder decodeObjectForKey:@"listOfCities"] retain];
self.listOfPlayers = [[aDecoder decodeObjectForKey:@"listOfPlayers"] retain];
NSLog(@"Cities = %d", [self.listOfCities count]);
NSLog(@"Players = %d", [self.listOfPlayers count]);
Run Code Online (Sandbox Code Playgroud)
由于您正在处理单例,因此您只需要在任何时候存在该类的单个实例.因此,您只想归档和取消归档该单个实例.
考虑这段代码(假设启用了ARC):
@interface Singleton : NSObject <NSCoding>
+ (id)sharedInstance;
@property (strong, nonatomic) NSString *someString;
@end
@implementation Singleton
+ (id)sharedInstance {
static Singleton instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[Singleton alloc] init];
});
return instance;
}
#pragma mark - NSCoding implementation for singleton
- (id)initWithCoder:(NSCoder *)aDecoder {
// Unarchive the singleton instance.
Singleton *instance = [Singleton sharedInstance];
[instance setSomeString:[aDecoder decodeObjectForKey:@"someStringKey"]];
return instance;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
// Archive the singleton instance.
Singleton *instance = [Singleton sharedInstance];
[aCoder encodeObject:[instance someString] forKey:@"someStringKey"]];
}
@end
Run Code Online (Sandbox Code Playgroud)
使用此模板,您可以归档/取消归档单例,如下所示:
// Archiving calls encodeWithCoder: on the singleton instance.
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:[Singleton sharedInstance]] forKey:@"key"];
// Unarchiving calls initWithCoder: on the singleton instance.
[[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"key"]];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2740 次 |
| 最近记录: |