Sabrina
Sabrina

Reputation: 617

NSUserDefaults Plist Creation Fails in Swift (but not Objective-C)

I'm converting one of my projects from Objective-C to Swift and I've run into an odd snag. Consider the following code (executed in -applicationDidFinishLaunching)...

Objective-C

Please excuse the messy one-liner

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

In my Objective-C project this works as expected. If I run my application for the first time and no plist exists, the defaults are registered and saved into a new plist during the next -synchronize call. If the plist already exists but a value is missing, it'll add that value from defaults. Makes sense.

Swift

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

In my Swift-exclusive project, the defaults get registered into memory, but they're never written to disk when -synchronize is called. I can test and verify that the default values exist in memory immediately after the code above is executed if I log a value...

println(defaults.objectForKey("showUnread"))

But the values are never saved to the plist. Even if I update one of my bindings from the interface (all of which save and persist perfectly fine), the defaults are not saved for the missing values. In fact, a plist will never be created for my application until I update one of my bindings.

And yet my Objective-C project, an almost verbatim translation of my Swift project, is working perfectly. I must be overlooking something simple, but my searches on Google and Stack Overflow have come up empty.

Troubleshooting Steps

  1. Created a new Swift project, copied Defaults.plist to the project and put the above code in -applicationDidFinishLoading. Exact same results.
  2. Deleted app cache and plist, emptied trash and restarted.
  3. I heard the cfprefsd process could be maintaining a link to the deleted files, but it works fine with the Objective-C code using the same bundle identifier.

Upvotes: 2

Views: 324

Answers (1)

rmaddy
rmaddy

Reputation: 318794

The call to registerDefaults never persists any data (in either language). It's just a fallback when looking up a value that doesn't exist. Your expectation that the data should be written to disk is incorrect.

Your call to synchronize doesn't do anything because you haven't set any values in NSUserDefaults.

Upvotes: 2

Related Questions