需要帮助使用单例实现 initWithCoder 和 NSUnarchiver
我无法弄清楚如何在 iOS 5 应用程序中进行存档。我有一个单例 SessionStore,如果它在初始化时存在,我想检索 plist 数据。 SessionStore继承自NSObject,有一个ivar,一个NSMutableArray *allSessions,我想从plist文件中加载它。这是 SessionStore.m 不确定问题是否明显或者您是否需要更多信息...谢谢! Nathan
#import "SessionStore.h"
static SessionStore *defaultStore = nil;
@implementation SessionStore
+(SessionStore *)defaultStore {
if (!defaultStore) {
// Load data.plist if it exists
NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];
NSFileManager *fileManager = [[NSFileManager alloc] init];
if ([fileManager fileExistsAtPath:pathInDocuments])
defaultStore = [NSKeyedUnarchiver unarchiveObjectWithFile:pathInDocuments];
} else
defaultStore = [[super allocWithZone:NULL] init];
return defaultStore;
}
+(id)allocWithZone:(NSZone *)zone {
return [self defaultStore];
}
-(id)init {
if (defaultStore)
return defaultStore;
self = [super init];
if (self)
allSessions = [[NSMutableArray alloc] init];
return self;
}
-(NSMutableArray *)allSessions {
if (!allSessions) allSessions = [[NSMutableArray alloc] init];
return allSessions;
}
-(void)setAllSessions:(NSMutableArray *)sessions {
allSessions = sessions;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:allSessions forKey:@"All Sessions"];
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [SessionStore defaultStore];
[self setAllSessions:[aDecoder decodeObjectForKey:@"All Sessions"]];
return self;
}
在 AppDelegate.m 中,它在终止时保存 plist 文件:
- (void)applicationWillTerminate:(UIApplication *)application
{
// Save data to plist file
NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];
[NSKeyedArchiver archiveRootObject:[SessionStore defaultStore] toFile:pathInDocuments];
}
I'm having trouble figuring out how to get the archiving to work in an iOS 5 app. I have a singleton SessionStore that I'd like to retrieve plist data if it exists upon initialization. SessionStore inherits from NSObject and has one ivar, an NSMutableArray *allSessions, which I want to load from the plist file. Here's the SessionStore.m Not sure if the problem is obvious or if you need more info... thanks! Nathan
#import "SessionStore.h"
static SessionStore *defaultStore = nil;
@implementation SessionStore
+(SessionStore *)defaultStore {
if (!defaultStore) {
// Load data.plist if it exists
NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];
NSFileManager *fileManager = [[NSFileManager alloc] init];
if ([fileManager fileExistsAtPath:pathInDocuments])
defaultStore = [NSKeyedUnarchiver unarchiveObjectWithFile:pathInDocuments];
} else
defaultStore = [[super allocWithZone:NULL] init];
return defaultStore;
}
+(id)allocWithZone:(NSZone *)zone {
return [self defaultStore];
}
-(id)init {
if (defaultStore)
return defaultStore;
self = [super init];
if (self)
allSessions = [[NSMutableArray alloc] init];
return self;
}
-(NSMutableArray *)allSessions {
if (!allSessions) allSessions = [[NSMutableArray alloc] init];
return allSessions;
}
-(void)setAllSessions:(NSMutableArray *)sessions {
allSessions = sessions;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:allSessions forKey:@"All Sessions"];
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [SessionStore defaultStore];
[self setAllSessions:[aDecoder decodeObjectForKey:@"All Sessions"]];
return self;
}
In AppDelegate.m it saves the plist file upon terminating:
- (void)applicationWillTerminate:(UIApplication *)application
{
// Save data to plist file
NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];
[NSKeyedArchiver archiveRootObject:[SessionStore defaultStore] toFile:pathInDocuments];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通常这样做的方法是拥有一个数据文件,在需要时将数据保存到其中,然后在对象初始化时将它们加载回来。就像这样:
然后,每当我愿意时,我都会调用 saveData 将数据保存回磁盘。这可能是每次
allSessions
发生变化,或者只是在应用程序终止/进入后台时发生一次。这取决于allSessions
更改的频率以及确保保存数据的重要性。请记住,单例的代码绝不是最好的 - 如果您担心
sharedInstancedispatch_once
或类似内容背后的推理。代码> 很花哨。我认为这比你的方法更好,因为你试图序列化整个单例对象而不仅仅是它的内容,我认为这更容易理解正在发生的事情,然后单例本身处理所有加载和保存,而不是让你的
NSKeyedArchiver
像您所做的那样溢出到应用程序委托中。The way I usually do this is to have a data file which I save things to when I need to and then load them back up when the object is initialised. So something like this:
Then whenever I want to, I would call
saveData
to save the data back to disk. That might be every timeallSessions
changes, or just once when the app terminates / goes into the background. That would depend on how oftenallSessions
changes and how crucial it is to ensure the data is saved.Please bear in mind that the code there for the singleton is by no means the best - search around here on StackOverflow for reasoning behind using GCD
dispatch_once
or similar if you're worried aboutsharedInstance
being racey.I think this is better than your method because you are trying to serialise the whole singleton object rather than just its contents which I think is a bit easier to understand what's going on and then the singleton itself handles all the loading and saving rather than having your
NSKeyedArchiver
spill out into the app delegate like you have done.