【问题标题】:NSUserDefaults Plist Creation Fails in Swift (but not Objective-C)NSUserDefaults Plist 创建在 Swift 中失败(但不是 Objective-C)
【发布时间】:2015-08-08 18:39:34
【问题描述】:

我正在将我的一个项目从 Objective-C 转换为 Swift,但遇到了一个奇怪的问题。考虑以下代码(在 -applicationDidFinishLaunching 中执行)...

Objective-C

请原谅凌乱的单行字

[[NSUserDefaults standardUserDefaults] registerDefaults:
    [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Defaults" ofType:@"plist"]]];

在我的 Objective-C 项目中,这按预期工作。如果我第一次运行我的应用程序并且不存在 plist,则在下一次 -synchronize 调用期间注册默认值并将其保存到新的 plist 中。如果 plist 已经存在但缺少某个值,它将从默认值中添加该值。有道理。

斯威夫特

let defaults = NSUserDefaults.standardUserDefaults()
let plist = NSBundle.mainBundle().pathForResource("Defaults", ofType: "plist")
defaults.registerDefaults(NSDictionary(contentsOfFile: plist!) as! [NSObject : AnyObject])
defaults.synchronize()

在我的 Swift 专有项目中,默认值被注册到内存中,但在调用 -synchronize 时它们永远不会写入磁盘。如果我记录一个值,我可以在执行上述代码后立即测试并验证内存中是否存在默认值...

println(defaults.objectForKey("showUnread"))

但是这些值永远不会保存到 plist 中。即使我从界面更新了我的一个绑定(所有这些都可以很好地保存和持久化),也不会为缺失值保存默认值。事实上,在我更新我的一个绑定之前,永远不会为我的应用程序创建 plist。

然而,我的 Objective-C 项目,几乎是我的 Swift 项目的逐字翻译,运行良好。我一定是忽略了一些简单的事情,但是我在 Google 和 Stack Overflow 上的搜索都是空的。

故障排除步骤

  1. 新建一个Swift项目,将Defaults.plist复制到项目中,并将上述代码放在-applicationDidFinishLoading中。结果完全相同。
  2. 已删除应用缓存和 plist,清空垃圾箱并重新启动。
  3. 我听说 cfprefsd 进程可能会维护指向已删除文件的链接,但它可以在使用相同包标识符的 Objective-C 代码中正常工作。

【问题讨论】:

    标签: objective-c macos swift nsuserdefaults


    【解决方案1】:

    registerDefaults 的调用永远不会保留任何数据(以任何一种语言)。这只是查找不存在的值时的后备。您对数据应该写入磁盘的期望是错误的。

    您对synchronize 的调用没有执行任何操作,因为您没有在NSUserDefaults 中设置任何值。

    【讨论】:

    • 我确实知道registerDefaults 不写入磁盘,但我一直认为它的目的是在这些值不存在时创建它们。如果synchronize 没有将默认值提交给您的plist,那么registerDefaults 的用途是什么?那么为什么Objective-C中的相同代码会将值保存到plist?
    • 1) Objective-C 代码不保存注册为默认值的值。如果您有数据持久化,它来自其他一些代码。 2) registerDefaults 的目的是提供一组内存值,如果尚未为给定键保存实际值。
    • 我在评论后想了更多你的答案,并意识到我问了一堆你已经回答的问题。所以我想我唯一剩下的问题是在应用程序首次启动时填充NSUserDefaults 的标准做法是什么?检查 nil 和 setObject?
    • 1) 定义“意外地在 Objective-C 中工作”。我在我的 Objective-C 应用程序中使用registerDefaults,它不会保留默认值。 2)你没有。无需填充NSUserDefaults。这就是registerDefaults 的用途。它允许您定义默认值,而无需将一堆初始值写入磁盘。只有当你有明确的值要保存时才调用setObject:
    • 如果我删除 plist 和应用程序缓存并重建我的应用程序然后退出应用程序而不与它交互,它将创建 plist 并且我的 Defaults.plist 的内容将保存在其中。在我的整个项目中,我没有使用setObject。它完全依赖于接口绑定。我不会争论这一点,因为我意识到我的疏忽现在可能出现在我的 Objective-C 项目中,而不是像我想象的那样在我的 Swift 项目中,但这看起来确实很奇怪。在启动时与NSUserDefaults 的唯一交互是我的问题中的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2021-09-07
    相关资源
    最近更新 更多