我已经对这个主题进行了长期而艰苦的研究,但找不到解决方案。我对 xcode 中的 iphone 应用程序开发非常陌生,所以请让答案易于理解,哈哈。我按照苹果的“你的第二个 iOS 应用程序”教程,让主详细信息应用程序完美运行,但现在我想保存用户输入的数据,以便在重置应用程序后显示。该代码与此处的苹果教程相同
提前致谢!
我已经对这个主题进行了长期而艰苦的研究,但找不到解决方案。我对 xcode 中的 iphone 应用程序开发非常陌生,所以请让答案易于理解,哈哈。我按照苹果的“你的第二个 iOS 应用程序”教程,让主详细信息应用程序完美运行,但现在我想保存用户输入的数据,以便在重置应用程序后显示。该代码与此处的苹果教程相同
提前致谢!
您需要做出两个主要决定:如何存储数据,以及何时存储/检索数据。让我们从如何存储数据开始。
如何存储数据
您可以采用三种主要方法:保存到文件、保存到 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 进行编码/解码,我们只需要对类的每个数据成员进行编码/解码。查看源代码,我看到它们是两个 NSString 和一个 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 ,其中包含存档文件的目录路径以及在生产代码中需要错误检查和处理的常见警告(例如,如果文件不存在怎么办)。
保存数据也很容易。我们可以向 BirdSightingDataController 对象添加如下方法:
- (BOOL)archiveToPath:(NSString *)path
{
BOOL success = [NSKeyedArchiver archiveRootObject:self.masterBirdSightingList];
return success;
}
何时存储数据
现在我们已经有了保存和恢复数据的代码,我们需要决定何时执行这些操作。在这里,我会稍微含糊一些,因为其他问题,例如整体应用程序结构,也会发挥作用。但是,由于与在后台运行相关的方法(例如applicationWillResignActive:和applicationWillEnterForeground: ),应用程序委托可能是管理列表归档和取消归档的候选对象。
在进入后台之前删除目击列表的内存副本是一件好事。这建议将用于创建存档的代码放在应用程序委托中。相反,您应该考虑延迟加载列表,即在您准备好显示它之前不要检索它,这建议将检索列表的代码放在 BirdSightingDataController 的 init 方法中。
现在您的挑战是在不过度耦合和过度复杂化您的应用程序的情况下完成所有这些工作。但我会将讨论留给另一个问答。