我对此主题进行了长时间的努力研究,但找不到解决方案。我是xcode的iphone应用程序开发的新手,所以请让答案易于理解大声笑。我按照苹果的“你的第二个iOS应用程序”教程,让主细节应用程序完美运行,但现在我想保存用户输入的数据,以便在重置应用程序后显示。代码与apple tutorial here
上的代码相同提前致谢!
答案 0 :(得分:2)
您需要做出两个主要决定:如何存储数据,以及何时存储/检索数据。让我们从如何存储数据开始。
如何存储数据
您可以采取三种主要方法:保存到文件,保存到SQLite数据库(使用或不使用包装器,如FMDB),使用CoreData。最终你会想要掌握SQLite和CoreData,但是现在我建议采用第一种方法。
如果要保存/读取文件,则需要确定格式。有许多不同的选项,包括XML,JSON,您自己的自定义格式等。事实上,对于“真实”项目,并且根据项目目标,JSON等格式可能是一个不错的选择。但是,我将讨论使用序列化存档,因为许多机制已经到位。
要将数据存储在存档中,您将使用 NSKeyedArchver 将数据写入文件。稍后,您将使用 NSKeyedUnarchiver 从文件中检索信息。这些类将数据编码/解码到字节流,然后通过线路发送,写入文件等。
您的主数据结构是名为 masterBirdSightingList 的NSMutableArray,因此归档程序需要对数组进行编码。 NSArray及其可变对应物已经知道如何对自身进行编码/解码:它们只对每个元素进行编码/解码以及一些簿记信息。所以这个谜题有一个缺失的部分。您需要指定如何编码/解码BirdSighting类的实例。
要指定此项,请修改该类,以便它实现 NSCoding 协议。在 BirdSighting.h 中,将@interface声明更改为
@interface BirdSighting : NSObject <NSCoding>
实施NSCoding很简单。我在上面提到过,各种数组类都知道如何自己编码/解码,即它们已经实现了NSCoding协议。好吧,对BirdSighting进行编码/解码,我们只需要编码/解码该类的每个数据成员。看一下源代码,我看到它们是两个NSStrings和一个NSDate。但是这些类中的每一个都已经实现了NSCoding。因此,为了对BirdSighting实例进行编码/解码,我们只需要告诉每个实例变量自己编码/解码。我们在您添加到BirdSighting类的方法 initWithCoder: 和 encodeWithCoder: 中完成所有这些工作。
注意:我正在掩饰的一个细节是归档器和键控归档器之间的区别。通常,您需要使用键控归档器,因此需要三个宏定义。说实话,我会创建NAME_KEY等,作为静态NSString常量而不是宏。
#define NAME_KEY @"name"
#define LOCATION_KEY @"location"
#define DATE_KEY @"date"
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_name = [aDecoder decodeObjectForKey:NAME_KEY];
_location = [aDecoder decodeObjectForKey:LOCATION_KEY];
_date = [aDecoder decodeObjectForKey:DATE_KEY];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:NAME_KEY];
[aCoder encodeObject:self.location forKey:LOCATION_KEY];
[aCoder encodeObject:self.date forKey:DATE_KEY];
}
还有一点需要注意,因为BirdSighting直接从NSObject继承(它没有实现NSCoding),所以我使用了self = [super init]
。如果父类 实现了NSCoding,您可能希望self = [super initWithCoder:aCoder]
。
有了上述内容,可以轻松保存到文件/从文件读取。在BirdSightingDataController的某处,可能在 initializeDefaultDataList 中,我们插入以下内容:
masterBirdSightingList = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
其中 path 是一个NSString,其中包含存档文件的目录路径以及有关在生产代码中需要进行错误检查和处理的常见警告(例如,如果文件不存在,该怎么办)。 p>
保存数据也很简单。我们可以在BirdSightingDataController对象中添加如下方法:
- (BOOL)archiveToPath:(NSString *)path
{
BOOL success = [NSKeyedArchiver archiveRootObject:self.masterBirdSightingList];
return success;
}
何时存储数据
现在我们已经有了保存和恢复数据的代码,我们需要决定何时执行这些操作。在这里,我会变得更加模糊,因为其他问题,例如整体应用程序结构,会发挥作用。但是,由于与在后台运行相关的方法,例如 applicationWillResignActive: 和 <,应用委托可能是管理列表归档和取消归档的候选者。 EM> applicationWillEnterForeground: 强>
在进入后台之前删除目击列表的内存中副本是一件好事。这建议将代码放在app委托中创建存档。相反,您应该考虑延迟加载列表,即在您准备好显示它之前不要检索它,这建议将代码放在BirdSightingDataController的init方法中检索列表。
现在您面临的挑战是如何做到这一切,而不会过度耦合并使您的应用过度复杂化。但我会把这个讨论留给另一个Q&amp; A。