我刚刚完成了iOS开发的第二个教程。当我添加一个新的目击时,它工作正常,并在目击列表中出现。但是,当我关闭iOS模拟器并重新打开它时,只有第一个条目(手动添加)。 iOS模拟器中是否应该有内部存储器,即使它已关闭并重新打开? 似乎有一些记忆,好像我将我的联系信息添加到联系人,当我重新打开它时它仍然存在。 如果是这样,我如何确保DataController文件中的数组类似地存储在模拟器/手机上,这样每次重新打开模拟器时它都不会自动清除?
由于
答案 0 :(得分:2)
如果要在会话之间保存数据,则需要使用持久存储。选项包括:
您可以使用plist文件。例如,如果您有NSArray *array
,则可以使用writeToFile
将其保存到plist:
[array writeToFile:filename atomically:YES];
然后您可以使用以下内容读取此数组:
NSArray *array = [NSArray arrayWithContentsOfFile:filename];
此技术仅适用于标准NSString
,NSNumber
等对象,而不适用于BirdSighting
等自定义对象。
对于BirdSighting
等自定义对象,您可以使用NSKeyedArchiver
and NSKeyedUnarchiver
。顺便说一句,这些通常不仅是用于保存像这样的小数据集的数据的有用类,但鉴于它在新的iOS 6状态保存功能中占有突出地位,所以值得熟悉这种模式。
您可以使用NSUserDefaults
。这非常适合应用程序设置和默认设置,但理论上也可用于保存数据。
您可以使用CoreData。这是对象持久性的首选iOS技术。它是一个功能强大且设计精良的框架(虽然有点复杂),并且非常适合处理更多大量数据。
您也可以使用SQLite。见Ray Wenderlich article on using SQLite。一旦开始使用SQLite,您可以考虑使用FMDB来简化编码工作。
例如,如果您想使用第二种方法NSKeyedArchiver
和NSKeyedUnarchiver
,那么您可能要做的第一件事就是让BirdSighting
符合{{1通过改变NSCoding
中的@interface
声明来说:
BirdSighting.h
其次,您必须在@interface BirdSighting : NSObject <NSCoding>
中编写两个NSCoding
方法,initWithCoder
和encodeWithCoder
,以定义可为此对象加载/保存的属性:
BirdSighting.m
现在可以分别使用- (NSArray *)keysForEncoding;
{
return @[@"name", @"location", @"date"];
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
for (NSString *key in [self keysForEncoding])
{
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
for (NSString *key in self.keysForEncoding)
{
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
和BirdSighting
加载并保存NSKeyedUnarchiver
。
因此,专注于加载目击事件,你必须(a)告诉NSKeyedArchiver
要查找的文件; (b)指示它在初始化期间读取该文件:
BirdSightingDataController.m
- (NSString *)filename
{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
return [docsPath stringByAppendingPathComponent:@"BirdSightings"];
}
- (void)initializeDefaultDataList
{
NSString *filename = [self filename];
self.masterBirdSightingList = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:filename])
{
self.masterBirdSightingList = [NSKeyedUnarchiver unarchiveObjectWithFile:filename];
}
if (!self.masterBirdSightingList)
{
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
BirdSighting *sighting;
NSDate *today = [NSDate date];
sighting = [[BirdSighting alloc] initWithName:@"Pigeon" location:@"Everywhere" date:today];
[self addBirdSightingWithSighting:sighting];
}
}
还可以定义保存数据的方法:
BirdSightingDataController.m
现在,您可以在添加目击时调用此- (BOOL)save
{
return [NSKeyedArchiver archiveRootObject:self.masterBirdSightingList toFile:[self filename]];
}
方法,例如:
save
就个人而言,不是每当用户对应用程序进行任何更改时保存它,我可能只是让我的应用程序委托在应用程序进入后台或终止时保存它(但这需要进一步更改,所以我不会现在进入那个)。
但希望此代码说明了如何使用- (void)addBirdSightingWithSighting:(BirdSighting *)sighting
{
[self.masterBirdSightingList addObject:sighting];
[self save];
}
和NSKeyArchiver
来保存和加载数据。显然,对于更复杂的场景,我通常会鼓励您考虑核心数据。但对于像这样的小数据集,这个归档模式可能很有用(正如我所说,值得熟悉,因为基本技术也用于iOS 6应用程序状态恢复)。