How to register user defaults using NSUserDefaults without overwriting existing values?

Solution 1:

From the documentation for -registerDefaults: (emphasis added):

The contents of the registration domain are not written to disk; you need to call this method each time your application starts. You can place a plist file in the application's Resources directory and call registerDefaults: with the contents that you read in from that file.

So your code was on the right track. This is how you register default defaults.

I usually use this in -applicationDidFinishLaunching::

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

Using a plist makes it easy to add and change defaults in your app, and it prevents you from making the mistake of using @"NO" as a value too.

Edit: Swift 3 variant:

 UserDefaults.standard.register(defaults: NSDictionary(contentsOf: Bundle.main.url(forResource: "Defaults", withExtension: "plist")!)! as! [String : Any])