iOS:如何保存在应用程序中创建的自定义对象
Posted
技术标签:
【中文标题】iOS:如何保存在应用程序中创建的自定义对象【英文标题】:iOS: How to save a custom object that is created in an app 【发布时间】:2011-09-03 21:58:29 【问题描述】:我一直在阅读有关保存对象、保存状态等方面的内容,但我仍然对保存从我的应用程序创建的对象时应该采取的路线感到有些困惑。我已经构建了一个应用程序,用户可以在其中创建具有流派、名称和频率的广播电台。一旦用户点击保存,“Radiostation”对象就会使用自定义类创建并存储在放置在 RootViewController 中的 NSMutableArray 中。虽然 RadioStation 对象可以存储在此数组中并在表格视图中正确显示,但很明显,一旦应用程序退出,这些对象将不再由应用程序持有。
此时我不确定我应该如何开始构建这个设计。我需要设置一个plist吗?我应该将 Core Data 与 SQLite DB 一起使用吗?我是否需要针对这两种情况研究 iOS 对象序列化?还是有我不知道的更直接的方法?
【问题讨论】:
我添加了两个答案,哪个最适合您可能取决于用户将在应用程序中拥有多少广播电台。如果是 10,我会选择NSCoding
,如果是 5,000,我会选择 Core Data,但如果是 50 或 100……那么目前还不清楚哪个更好。
Plist 文件和一般的 xml,在 iOS 上并没有真正使用。它们被认为是浪费空间,除非你把它们拉上拉链。但是压缩文件会使它们的读取/写入速度不必要地变慢。
@Abhi:在 iOS 上“没有真正使用”?谁说的?我一直在使用它们。 :) 如果您谈论的是实际的磁盘空间使用情况,它们是一种出色的低开销数据格式。它们可以以二进制格式存储。直接使用NSPropertyListSerialization
代替便捷方法即可。
@quixoto 二进制属性列表没有NSCoding
的灵活性或 XML plist 的人类可读性。我永远不会使用它们。
但是说“Plist 文件和一般的 xml,并没有真正在 iOS 上使用”和说“我永远不会使用它们”之间是有区别的
【参考方案1】:
本地持久化数据的三种方式:
-
使用托管对象或 SQLite 将对象存储在数据库中
使用各种类的 writeToFile 将对象存储在沙箱中的文件中
将数据存储在 NSUserDefaults 中
如何持久保存对象数据取决于您使用它的方式以及您保存的数据类型。如果您有很多相同类型的对象,CoreData 就很有意义,并且 SQL 的搜索和排序机制会很有用。我倾向于将沙箱用于非常大的文件,例如图像、声音文件和通过 NSData 反弹的大量数据。我将 UserDefaults 用于可能被视为“首选项”的少量数据。
你可以把任何东西放在你想要的任何地方,我建议你在开始一个新项目时熟悉这三种机制。其他技术,例如使用 NSCoding 序列化和反序列化类,可用于更轻松地保存数据。请注意,一旦您实现了 NSCoding,您就可以在任何地方存储数据,甚至可以通过网络发送数据。
对于您的 RadioStation,我个人会使用 UserDefaults。使用 NSCoding 的好处是,一旦你实现了 initWithCoder 和 encodeWithCoder,你可以很容易地流式传输对象的层次结构(例如,自定义对象的数组,每个对象可能包含字典、数组或自定义对象等)。如果您要保存的唯一内容是字符串数组,那么直接使用 UserDefaults 就足够简单了。
【讨论】:
【参考方案2】:最强大的方法是让您的自定义对象成为NSManagedObject
的子类,并使用Core Data 将其存储在NSManagedObjectContext
中。在 iOS 上,这将始终使用 sqlite 数据库,在 Mac OS X 上,您可以使用 sqlite、xml 或专有的二进制格式(比 xml 更小/更快)。
根据您的数据结构的复杂程度以及未来发生变化的可能性,这种技术对于您的应用来说可能会也可能不会太复杂。设置工作量很大,API 也很复杂,但如果需要在一个文件中存储数万/数百万个对象,它是最佳选择。
对于您的应用,我将有一个包含应用中所有广播电台的 sqlite 文件。
最简单的选择是在自定义对象的类中实现NSCoding
协议。记录在这里:
http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html#//apple_ref/doc/uid/20000948-BCIHBJDE
基本理论是您的对象将其所有数据写入或读取到“编码器”,然后将编码器传递给任何子对象。在课堂之外,您可以使用“归档”或“取消归档”类来协调所有内容。
一旦您的自定义类实现了NSCoding
,您就可以通过以下方式读取/写入磁盘:
myObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
[NSKeyedArchiver archiveRootObject:myObject toFile:filePath];
这是一种非常简单的方法,但它有一些缺点,例如,您需要找出自己的方法来支持不同版本的文件格式(例如,可能具有不同的文件扩展名)。
Cocoa/CocoaTouch 中的许多类已经实现了NSCoding
,因此可以以这种方式将它们写入文件(包括NSArray
、NSString
、NSNumber
等)。
对于您的应用,我会使用它来将每个广播电台存储在一个文件中。当应用程序启动时,从一个目录加载所有广播电台。您应该考虑为您的应用启用 iTunes 拖放文件共享,以便用户可以轻松地与朋友或设备之间共享电台文件。
这也很适合 iCloud 在设备之间同步,我对 iCloud 的研究不多,但我希望每个广播电台一个文件将是实现 iCloud 同步的理想方式。
【讨论】:
您应该编辑原始答案以添加这个额外的细节,而不是添加另一个答案。 @Abizem 它们是两个完全不同的答案,两种有效方法都取决于问题中未提供的详细信息。你读过吗? 请只使用一个答案,即使有多种解决方案。谢谢 iOS 应用用于“filePath”的最佳目录是什么? 您可以使用NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
获取应用程序文档文件夹的路径。查看标题为“实现常见应用程序行为”的文档以获取更多信息。只需将该路径与斜杠和您的文件名连接起来,您就会得到一个文件路径。【参考方案3】:
不需要这些东西。如果你只有一件事要保存,那么研究一下 NSArray 的这个方法:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
如果您的用户可以保存许多广播电台,那么您可能想研究一下 CoreData,它有一点曲线,但最终将是最简单的方法。
【讨论】:
这不适用于自定义对象。对于自定义对象,根据上述答案,NSCoding 是正确的。 writeToFile/arrayWithContentsOfFile 在您仅使用属性列表对象 (developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…) 时是一种非常有用的方法。以上是关于iOS:如何保存在应用程序中创建的自定义对象的主要内容,如果未能解决你的问题,请参考以下文章
如何本地化在 Hybris 的 trainingcore-items.xml 中创建的自定义类型?
带有在 IB 中创建的自定义视图的 InputAccessoryView
iOS 开发 - 如何使用自定义 Table View Controller 显示在 Interface Builder 中创建的静态单元格?