【问题标题】:Setting NSUserDefaults Directly In Custom Getter / Setter直接在自定义 Getter / Setter 中设置 NSUserDefaults
【发布时间】:2014-03-10 16:25:09
【问题描述】:

所以我有一个小值需要通过 NSUserDefaults 在我的应用程序中同步。我发现自己从 NSUserDefaults 中保存并获取了一些值,我认为将 Getter / Setter 直接链接到 NSUserDefaults 可能会很好。

这是我的 Getter / Setter 代码:

- (void) setSomeProperty:(id)someValue {
    [[NSUserDefaults standardUserDefaults]setObject:someValue forKey:@"someProperty"];
}

- (id) someProperty {
    return [[NSUserDefaults standardUserDefaults]objectForKey:@"someProperty"];
}

这是我的访问方式:

someClass.someProperty = @"SomeValue"; // -- Set's To @"SomeValue"

id someValue = someClass.someProperty; // -- Assigns Value From NSUserDefaults

这样,当我更新或检索属性时,它总是直接访问 NSUserDefault 值。对我来说,这似乎是一种更简单的方式来写入和检索我的 NSUserDefaults 中的值,但我可能忽略了一些问题或性能考虑。感谢您提出反馈/疑虑。

问题

这是可以接受的做法吗?这会在以后引起问题吗?

【问题讨论】:

  • 我做同样的事情。我从未见过问题。
  • 我认为这样做绝对没问题,只是在将值保存为默认值时应该调用同步
  • @AndreyChernukha 您无需在每次设置值时都调用synchronize。操作系统有时会自动同步默认值。
  • 谢谢@rmaddy,我现在可以安心地继续前进了!
  • @rmaddy 如果要保证始终保存该值,请致电synchronize。如果您在调试时使用 Xcode 终止应用程序,或者如果应用程序在您更改值后不久崩溃,它可能不会总是被保存,除非您调用 synchronize。不过,我同意这不是必需的。

标签: ios objective-c properties nsuserdefaults


【解决方案1】:

你所做的没问题,但有一些你应该注意的含义。

NSUserDefaults 是基于磁盘的存储。因此,它比基于内存的解决方案要慢得多。在 iOS 上,“基于磁盘”是指闪存,它仍然比基于内存的存储慢得多。

闪存在失败之前也有有限数量的写入周期。

出于这两个原因,我不会将上述技术用于快速变化的值或需要快速响应的地方。

另外,我假设既然您说“...在我的应用程序中同步...”,您的意思是在多个对象之间共享。

我建议确保在您的标题中记录这些属性,以便清楚地表明它们是共享的、持久的属性。除了标题中的描述性文本之外,在这些属性名称中添加“共享”或“保存”字样会有所帮助。

如果您的唯一要求是共享访问,并且您不需要持久性,您可能会考虑使用数据容器单例而不是使用用户默认值。 (您创建一个具有要共享的属性的单例对象,然后从应用程序中的任何位置获取指向该单例的指针,并使用它来读取/写入您要共享的属性。)

您甚至可以使用混合方法,在单例中收集这些属性,并在单例中实现持久性。这具有将保存/读取逻辑集中在一个地方的优势,因此如果您决定在将来某个日期使用不同的存储方法,可以将其更改为使用不同的存储方法。

【讨论】:

  • 感谢 Duncan,它已经设置为会话资源的单例,只是将其用于需要在应用关闭时保存的几个值!缓存系统也是flash,还是只是同步过程?
  • iOS 中的所有持久存储都是闪存。这就是 iOS 中“硬盘”的用途。
【解决方案2】:

就个人而言,我发现在您希望使用的过程中获取默认值会更好。所以:

NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

NSString* myValue = [defaults stringForKey:@"mykey"];
//manipulate myValue;

...您可以在代码中清楚地看到您的意图。

【讨论】:

  • 调用someClass.someProperty的抽象可以让代码看起来更干净,更容易阅读。此外,它还减少了您可能不小心输入@"myKey" 而不是@"mykey" 的位置,并且也使维护变得更简单。
  • 我想,这是有道理的。不过,我通常将密钥保存在一个常量文件中。
【解决方案3】:

没有技术理由不这样做。有些人会告诉您,一个属性可能会向其他开发人员发出信号,表明它是一个简单的 getter/setter,而不是调用从硬盘驱动器或远程服务器读取的东西。

它可能取决于上下文 - 如果您以一种传达它是某种与存储相关的对象的方式命名您的类,那么它可能会更好。除非您过度使用属性(在内部循环内部,在计算中多次检索它而不是使用变量等),否则您不会遇到性能问题。否则我会使用 2 种方法,而不是在他们的名字前面加上“load”/“read”和“save”/“write”前缀,这样其他开发人员就知道他们应该缓存这些值,并且只在需要数据时才调用它们迄今为止。

编辑:不过,对于 99% 的情况,您可以按照您的描述进行操作。就我个人而言,这就是我所做的,但我认为您应该了解我在答案中描述的问题。

【讨论】:

  • 使用属性设置不是简单的 getter/setter 而是与存储相关联的先例:Core Data 模型对象。我认为使用NSUserDefaults 执行此操作也是完全可以接受的,因为开销非常小。只有当您开始在 NSUserDefaults 中存储大量数据,或者可能在循环中多次设置内容时您可能会遇到问题,但大多数情况下您根本不必担心。
  • @Gavin 我同意,编辑了我的评论。另外,CoreData 不会缓存对 NSManagedObjects 的更改,然后在您调用某些特定函数时提交它们吗?我不认为属性实际上与存储相关联,并在您为属性设置新值时对其进行修改。但是自从我使用 CoreData 以来已经有一段时间了...
猜你喜欢
  • 2023-03-12
  • 2012-09-09
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2017-08-23
  • 1970-01-01
相关资源
最近更新 更多