【问题标题】:What are the limitations of NSUserDefaults?NSUserDefaults 的限制是什么?
【发布时间】:2011-09-04 15:24:55
【问题描述】:

在 iPhone 中永久存储数据通常使用 Core Data 或 sqlite3 完成。大多数人更喜欢将 NSUserDefaults 用作应用程序偏好的存储,而不是将其用作普通数据库(例如 sqlite)。

我发现 NSUserDefaults 可以存储大量数据,它非常好用而且速度很快。那么为什么不将其用作永久存储呢? NSUserDefaults 作为数据库有什么限制?

更新:
我经常使用三种不同的方式将数据保存到磁盘。

  • 核心数据
  • 将对象序列化为 plist
  • NSUserDefaults

我不再使用 FMDB(或直接使用 sqlite)了。 每种方法的主要优点和缺点是什么?

我遇到的 NSUserDefaults 的一些优点:

  • 使用 NSPredicate 可以轻松完成排序、分组等操作。
  • NSUserDefaults 是线程安全的。
  • 只需一行即可获取数据并将其保存到 NSUserDefaults。

【问题讨论】:

  • sqlite3对于保持大数据库更有效,搜索速度更快,权限多。
  • 但是当存在大量数据时,将数据存储在 nsuserdefaults 中会导致任何问题吗? sqlite3 有什么特权?
  • 第一个也是主要的特权是您可以在 sqlite3 数据库中快速排序、分组、搜索

标签: iphone objective-c core-data nsuserdefaults


【解决方案1】:

Sqlite3 对于保持大型数据库和访问数据库元素更有用。您可以对Sqlite3 数据库的项目进行排序,您可以非常快速地在Sqlite3 数据库中搜索项目。 Sqlite3 数据库有很多NSUserDefaults 没有的权限!


NSUserDefaults vs Sqlite3

NSUserDefaults 用于用户偏好,通常是基本对象,如 NSString 或 NSNumber。 Sqlite、序列化属性列表中的对象集合或 Core Data 都是存储用户数据(例如您创建的模型对象)的有效选项。

您不会看到速度差异,但最好还是为您正在做的事情选择正确的机制。如果只是偏好,那么使用 NSUserDefaults,否则我会将您的对象序列化为 plist。如果您是 Cocoa 的新手,我会首先避免使用 Core Data 甚至 Sqlite,让自己有机会先学习基础知识。


NSUserDefaults or Sqlite

当你想存储大量的数据时,如果你想存储较少的值,就选择 Sqlite,选择 NSUserDefaults。 Sqlite 占用一些内存,所以只有在你真正需要保存复杂数据时才使用它。


Using NSUserDefaults to save a lot of game data

通常 NSUserDefaults 用于保存游戏设置。要保存游戏数据,通常最好使用 SQLite,或者您可以创建对象的 NSDictionary 并保存到磁盘,这里有几篇文章可能会有所帮助:

  1. http://www.cocos2d-iphone.org/forum/topic/9308
  2. http://www.cocos2d-iphone.org/forum/topic/9210

【讨论】:

  • 并非如此。这是我想知道的。谢谢。
  • @ViToBrothers 如果我们将 Dictionary 存储在 NSUserDefaults 中会怎样?
  • @rptwsthi,我也有同样的问题。我有一张发票,其中包含添加到 NSMutableArray 的行项目。如果我将它存储在 NSUserDefaults 中会发生什么?是好还是坏?订单项可能是 1 个或 2 个,甚至可能是 100 个订单项! O.o
  • @vishman 我们可以存储这么多数据,但这绝不是一个好习惯。如果应用程序崩溃,您始终有丢失数据的风险。
  • :) 太棒了!我正在考虑的确切事情!谢谢!我想就像我上面提到的任何情况一样,我们应该使用临时表来存储我们的数据,对吗?这是唯一的最佳实践!(CoreData 或只是纯 SQLite 实现)我的梦想是成为一名优秀的 iOS 工程师。这就是我开始怀疑这些事情的地方!感谢您的想法! (y)
【解决方案2】:

对于我目前正在进行的一个项目,我需要建立一个大型数据库(大约 400.000 条记录)。如果您使用 NSUserDefaults,则必须添加记录,这可能需要几分钟(取决于设备和导入数据的方式)。如果您使用 CoreData,您只需将预构建的数据库复制到应用程序的文档目录并立即使用。

这就是我依赖 CoreData 的原因。

【讨论】:

    【解决方案3】:

    NSUserDefaults 提供了一个简单的学习曲线和线程安全的实现。

    否则,我发现 Core Data 在各方面都更胜一筹。尤其是在配置默认值和迁移例程方面。

    编辑:事实证明,NSUserDefaults “线程安全”似乎来自于在主线程上运行的操作。这在我的一个应用程序中造成了严重的跳帧;我最终撕掉了 NSUserDefaults 并用一个线程安全的 NSMutableDictionary 替换它,它被序列化为一个文件。

    【讨论】:

    • 我可以像使用 NSUserDefaults 一样使用 Core Data 作为字典吗?就像存储键的值一样?老实说,我对 Core Data 了解不多。保存的数据是否可以是像 plists 这样的分层数据库?有没有好的教程如何以这种方式保存一些数据?
    • 参见“用户信息词典”developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 可以将 NSDictionary 序列化为 NSData。因此,您可以将 NSDictionary 保存为实体的属性。 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 您可以通过定义根级实体没有父级的实体和关系来创建分层数据库。
    • 希望我能投票更多次 - 我的应用程序被偶尔冻结数周所困扰,现在解决方案很明显!如果数据存储阻塞主线程,它究竟是“线程安全”的?非常误导
    【解决方案4】:

    CoreData 的一个优点是您的对象将是具有属性的 NSManagedObject。这意味着当您获取或设置值时,您将拥有自动完成功能来帮助您了解属性名称。它还使代码更具可读性。

    同时使用 NSUserDefaults,您必须始终使用键值访问器,使用字符串作为键。

    即:

    myGlobalSettingsObject.lastLoginTime = @(now);

    对比

    [[NSUserDefaults standardUserDefaults] setValue:@(now) forKey:@"lastLoginTime"];

    如果您在某处设置密钥时不小心打错了怎么办?编译器不会警告你。如果有人在某个地方输入了错误的类型怎么办?编译器不会警告你。

    例如:

    [[NSUserDefaults standardUserDefaults] setValue:@"now" forKey:@"lastLoginTiem"]; ^ ^ ^^^^

    ...在构建时不会导致警告或错误...危险!

    使用 NSManagedObject 的其他好处是它可以进行验证;它可以确保非空值;它可以有自定义的 getter 和 setter 方法,你可以用它们来做一些很酷的事情;如果您更改所有值的存储方式,它可以处理自动迁移;并且它的数据模型将成为您存储库的一部分,因此您可以轻松跟踪它的更改历史记录。

    同时,NSUserDefaults 又快又脏,非常适合基本的小应用程序,但它只是非常原始。对于小型应用程序来说很好,但如果你有一个巨大的应用程序,与使用 Core Data 相比,它会变得难以管理。

    关于 NSUserDefaults 唯一可能的事情是,如果您的应用需要删除其 CoreData 存储,或者您不想为实现线程安全的 CoreData 而烦恼,那么在这方面它的维护成本较低。

    【讨论】:

      猜你喜欢
      • 2012-12-13
      • 2010-09-11
      • 2012-03-22
      • 2019-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      相关资源
      最近更新 更多