61
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"xxxxxxxx" forKey:@"name"];

[defaults synchronize];

I need to know why do i have to use the last line of the above code [defaults synchronize] ? What is the purpose of using it? Is it a must ?

xǝlɐ
  • 63
  • 1
  • 11
shajem
  • 2,111
  • 5
  • 22
  • 30

4 Answers4

108

The purpose of [default synchronize]; is to make the user defaults get written on disk immediately. You don't need to call it explicitly, iOS already does it at appropriate moments. So you can remove that line. In fact, it's a performance problem if you call synchronize every time you set a default.

Prior to iOS 7, the user defaults were always synchronized when the application transitioned into background. As of iOS 7, that is no longer the case, so you might want to call synchronize in your app delegate's applicationDidEnterBackground: or register to the UIApplicationDidEnterBackgroundNotification notification to do that.

From the documentation for -[NSUserDefaults synchronize]:

Because this method is automatically invoked at periodic intervals, use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes.

Pang
  • 9,564
  • 146
  • 81
  • 122
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • So you say there will be issues with performance if i do so every time ? So is it ok if i omit that line, the code anyway works with out it. – shajem Mar 10 '12 at 16:24
  • You can if you're not planning on using the `name`-object for a while. – Emil Mar 10 '12 at 16:39
  • 6
    Yes, your code will work just fine without that line. Your setting will be written to flash by iOS automatically later. It will be written when your app goes into background, at the latest. Beware when you're debugging, though: if you kill the app by pressing the "stop" button or when your app crashes, then it's possible that the settings have not yet been written. – DarkDust Mar 10 '12 at 16:43
  • 12
    @Emil: Wrong, you can immediately access the key `name` again. It's already in memory, but just not yet written to flash. – DarkDust Mar 10 '12 at 16:44
  • 2
    in iOS7, I do not think it writes it to flash when the app goes to the background, you have to explicitly synchronize when it enters background in appdelegate – resopollution Sep 21 '13 at 10:30
  • I agree its not happening automatically for me in iOS 7 either. I added it to applicationWillResignActive. – Andrew Smith Oct 10 '13 at 22:35
  • According to the official described: "The synchronize method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database." But why is iOS7, we need call synchronize? – MeganZhou Mar 31 '14 at 06:08
  • 3
    @MeganZhou My guess is that Apple now does synchronize from time to time, but they do not synchronize when going into background any more. This now means that the following can happen: Apple synchronizes the user defaults, you write a new value, app goes into background (user defaults are _not_ synchronized), app gets killed (for example due to memory pressure). Now your new value was not saved. So just synchronize when the app goes into background. There is _no_ need to call `synchronize` at any other time! Do _not_ call `synchronize` all the time, it will kill app performance. – DarkDust Mar 31 '14 at 07:36
  • I agree with your answer. Thanks a lot. – MeganZhou Mar 31 '14 at 09:37
  • 1
    I'm not getting why you guys don't synchronize during 'applicationWillTerminate' rather than 'applicationDidEnterBackground' ? Since applicationWillTerminate will always be called at kill time, which is what we want to be careful about. – nembleton Jun 21 '14 at 17:04
  • @nembleton: No, it's [not always called](http://stackoverflow.com/questions/7818045/applicationwillterminate-when-is-it-called-and-when-not) (note the *may* in the documentation). It's also not called when your app crashes, obviously. – DarkDust Jun 23 '14 at 07:42
  • @DarkDust yeah I did notice that. Didn't know it was that bad though... This is really stupid from Apple... Anyway, adding it at least to didEnterBackground does seem the way to go. Thanks for the note. – nembleton Jun 23 '14 at 08:49
  • Don't think this covers crashes. e.g. what happens if you write to defaults, don't synchronize, and sometime after your app crashes. I believe in that case you will lose your changes. So is it best to always synchronize after a write? – lostintranslation May 31 '17 at 13:50
  • 1
    @lostintranslation: Yes, in this case you lose the changes. But only call `synchronize` immediately for "important" data where it's really inconvenient for the user if that setting is lost. Writing the user defaults takes some time and if you `synchronize` too often you may notice this (e.g. UI hanging/stuttering for a short time). – DarkDust May 31 '17 at 16:01
23

You don't have to write that line anymore.

The method reference from the updated documentation

Waits for any pending asynchronous updates to the defaults database and returns; this method is unnecessary and shouldn't be used.

Comments to the method explaining what to do.

     /*!
     -synchronize is deprecated and will be marked with the NS_DEPRECATED macro in a future release.

     -synchronize blocks the calling thread until all in-progress set operations have completed. This is no longer necessary. Replacements for previous uses of -synchronize depend on what the intent of calling synchronize was. If you synchronized...
     - ...before reading in order to fetch updated values: remove the synchronize call
     - ...after writing in order to notify another program to read: the other program can use KVO to observe the default without needing to notify
     - ...before exiting in a non-app (command line tool, agent, or daemon) process: call CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
     - ...for any other reason: remove the synchronize call
      */
     open func synchronize() -> Bool
Seryozha
  • 1,649
  • 1
  • 14
  • 13
17

In iOS 12 release notes you can find this information:

NSUserDefaults has several bug fixes and improvements:

Removed synchronization requirements. It's no longer necessary to use synchronize, CFPreferencesAppSynchronize, or CFPreferencesSynchronize. These methods will be deprecated in a future version of the OS.

If your target devices are iOS 12 or newer, according to the above release notes it should work without a call to synchronize. However, if you still support iOS 11 and lower, you still might want to call the synchronize method.

Heefan
  • 385
  • 2
  • 8
Leszek Szary
  • 9,763
  • 4
  • 55
  • 62
5

Yes, with that line you are telling your system to upload the NSUserDefaults with your new defaults.

You can find all the information here:

Cœur
  • 37,241
  • 25
  • 195
  • 267
Antonio MG
  • 20,382
  • 3
  • 43
  • 62