18

Please, anyone, help me: Is calling NSUserDefaults's synchronize() method mandatory?. If I don't call it, what will happen? My application is working fine without it.

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
Balagurubaran
  • 549
  • 6
  • 18

4 Answers4

25

No.

Since iOS12, it isn't mandatory anymore. Apple says:

This method is unnecessary and shouldn't be used.

You can find more information on iOS12 release note:

UserDefaults

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.

Now that you don't need to call these synchronization methods, the performance characteristics of NSUserDefaults and Preferences Utilities are slightly different: The time taken for enqueueing write operations is now paid by the writing thread, rather than by the next thread to call synchronize or do a read operation.

Community
  • 1
  • 1
CoyBit
  • 1,592
  • 1
  • 17
  • 19
  • 3
    However documentation does not specify from which iOS version this statement is true. Besides in my tests on device with iOS 12 without a call to synchronize my saved value was sometimes lost if I killed the app few seconds after saving the value. – Leszek Szary May 17 '19 at 12:41
  • @LeszekSzary good point. Your answer is iOS12. I've updated my response. https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes/foundation_release_notes?language=objc – CoyBit May 17 '19 at 14:54
  • 5
    Even on iOS 13, if you kill the app immediately after writing a value, it won't be saved without a call to synchronize. – Senseful Dec 15 '19 at 09:49
  • In my testing it writes just after 1 second after the last set value. – malhal Mar 26 '20 at 13:07
  • I'm testing an iOS 12 app and I also find that data is sometimes lost if I save to defaults shortly before killing the app. So I don't entirely trust that Apple docs statement for these particular cases. Seems like calling `synchronize()` may still have some usefulness if you need to tell the app to synchronize default prior to it being moved to background, terminated, resign active, etc. – peacetype Dec 05 '21 at 02:48
18

From the docs:

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.

Meaning that if you kill the app right after something is written to the defaults without the periodic interval catching it, it will get lost. You probably did not kill the app right after a write event yet which is why your app seems to work fine so far.

luk2302
  • 55,258
  • 23
  • 97
  • 137
  • 9
    What is the system interval for writing ? The docs are (as always) very unspecific. – NikkyD Nov 21 '16 at 16:26
  • 2
    Would this cover 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:43
  • 3
    This answer is no longer relevant because it cites the old documentation. @CoyBit's [answer](https://stackoverflow.com/a/47313330/666757) is now the correct one. – Nathan Hitchings Apr 20 '18 at 21:14
5

Normally it works perfectly fine and you only have to use it in special cases, for example when the app will close directly after writing to NSUserDefaults. So you can simply add the synchronize method to the corresponding AppDelegate-method.

matthiaswitt
  • 196
  • 9
5

As others have said, you don't normally have to call synchronize at all.

Normally the system calls it for you so your defaults changes get written.

However, when working with Xcode it's pretty common to terminate your app by pressing command period or clicking the stop button. In that case it terminates the app without warning and your user defaults changes will quite likely not be written out, and will be lost.

This can be a good thing or a bad thing, depending on what you want. It's certainly confusing.

You can "fix" it by calling synchronize each time you make a change, or on some time interval. However that does slow your app down and increase it's power requirements (both by very small amounts.) If you are in a loop, writing changes to 10,000 server or Core Data records, and you change user defaults after each pass, then calling synchronize after each one might have a measurable effect on app speed and on battery life. In most cases you're not likely to notice the difference however.

Duncan C
  • 128,072
  • 22
  • 173
  • 272