我想知道准则的用途:
1 - 我多久可以从NSUserDefaults读取
2 - 我可以在NSUserDefaults中合理存储多少数据
显然,NSUserDefaults可以使用多少是有限的,但我无法确定哪些是合理的,哪些是不合理的。
其他一些例子:
如果我的游戏有计算机作为其中一个玩家的选项,我将使用NSUserDefaults来保存该布尔值。这很清楚。但是,每当我想知道计算机是否是一个播放器或我是否应该使用实例变量时,在我的游戏中访问NSUserDefaults也是合理的吗?假设我需要每秒检查一次布尔值。答案是否相同是100毫秒而不是?每隔10秒钟呢?
如果我的游戏有50个移动对象,并且我希望在用户退出应用程序时存储他们的位置和速度,那么NSUserDefaults是存储该数据的合理位置吗? 20个移动物体怎么样?怎么样200?
答案 0 :(得分:16)
经常这样。期望默认值的开销类似于线程安全的NSDictionary我想知道指导原则是什么: 1 - 我多久可以从NSUserDefaults读取
物理上,超过你需要它。逻辑最大值是你需要多快,以及它在磁盘上占用多少空间。还要记住,这个表示是在启动/关闭时以及其他各种时间从磁盘读取的。2 - 我可以在NSUserDefaults中合理存储多少数据
如果我的游戏有计算机作为其中一个玩家的选项,我将使用NSUserDefaults来保存该布尔值。这很清楚。但是,每当我想知道计算机是否是一个播放器或我是否应该使用实例变量时,在我的游戏中访问NSUserDefaults也是合理的吗?
只需向对手添加const bool
即可。零运行时丢失,除了内存,这将不会很重要。
假设我需要每秒检查一次布尔值。答案是否相同是100毫秒而不是?那么每隔10秒呢?
再次,它就像一个线程安全的NSDictionary(散列)。它会相当快,而且足够快,可以在那个频率上阅读。它是否是最好的设计取决于该计划。如果它变得巨大,那么表演就会受到影响。
如果我的游戏有50个移动物体,并且我希望在用户退出应用程序时存储他们的位置和速度,那么NSUserDefaults是一个存储该数据的合理位置吗? 20个移动物体怎么样?怎么样200?
它会没问题,虽然我不会在游戏过程中通过用户默认值进行读/写;只需根据需要保存/加载状态。
我不建议将所有这些保存在用户默认值中。只需为您的游戏状态创建一个文件表示,并使用用户默认值来设计它的目的。如果它很大并且你经常写它,那么实现可能会定期将状态刷新到磁盘,这可能需要相当长的时间。
答案 1 :(得分:14)
不要担心限制。相反,问问自己这个简单的问题:
这是偏好吗?
如果是偏好,那么它应该是用户默认值。这就是用户默认的用途。如果没有,那么它应该在Documents目录中(或者在Mac上,可能在Application Support中)。
在iOS上,您可以通过(如果可能)将其放入设置包中以便在“设置”应用程序中进行显示和编辑来判断是否适合。在Mac OS X上,您通常可以通过将它放在“首选项”窗口中是否合适来判断它是否是首选项。
当然,这取决于你的判断。例如,Stanza for Mac错误地将非首选项置于其“首选项”窗口中。
您也可以通过相反的方式来考虑这个问题:
这是用户创建的数据吗?
您将拥有默认值的首选项不是用户创建的数据;它是用户覆盖的数据。失去它也同样糟糕,但它告诉你应该保留它。
答案 2 :(得分:10)
这里没有人提到的主要性能问题是用户的主目录可能在网络卷上,并且可能不是特别快。这不是一个理想的情况,但它会发生,所以如果你担心性能是你应该测试的。
也就是说,NSUserDefaults
使用内存缓存,并且仅在同步时产生成本。根据文档,同步“自动...定期间隔”;我相信这只适用于某些事情发生了变化的情况。
因此,对于检查计算机是否为播放器的情况,一旦帧被缓存就不应该使用NSUserDefaults
。对于存储游戏状态,如果你经常更新它可能会出现性能问题,正如Peter Hosey所说,这是一种语义滥用。
答案 3 :(得分:7)
NSUserDefaults中有数百个项目可以使用(它基本上只是属性列表序列化的包装)。关于应用程序的开销,最好的办法是尝试并使用分析器。
答案 4 :(得分:2)
NSUserDefaults基本上是一个包装器,用于从磁盘加载.plist文件中的NSDictionary(并将其写入磁盘)。您可以在NSUserDefaults中存储尽可能多的数据,但是您几乎无法控制它使用的内存量以及它从磁盘中读取的内容。
我会针对不同的信息/数据使用不同的技术。
来自服务器,首选项,用户信息等的一小部分数据,我会使用NSUserDefaults。
对于登录信息(访问令牌,敏感数据),我会使用钥匙串。钥匙串也可用于删除应用程序时不应删除的数据。
对于大量的服务器数据或游戏数据,我会将其写入磁盘,但请将其保存在内存中。
在你的情况下,我会将它保存在内存中(可能是@property),但是我会定期将它写入磁盘(可能每隔1到5次更改一次,使用int ivar)。确保此磁盘写入方法位于AppDelegate中,以便在关闭正在执行它的视图控制器时它不会失败。
这样,数据很容易被访问,但它也被保存到磁盘上以便安全保存。