9

I have an app and it calls to variables often. And these variables are stored in NSUserDefaults.

I'm wondering where NSUserDefaults is storing? And if I call NSUserDefaults directly instead of using variables.

Which is faster? variables or NSUserDefaults. Because using variables to store NSUserDefaults will be the cause of using more memory.

pkamb
  • 33,281
  • 23
  • 160
  • 191
TomSawyer
  • 3,711
  • 6
  • 44
  • 79
  • you can use directly if you don't need variable for future use , otherwise you need to fetch all time – Prashant Tukadiya May 24 '16 at 10:16
  • Not getting your question properly – Ketan Parmar May 24 '16 at 10:17
  • I'm caring about speed, variables is being stored in ram (memory) but i don't know how does `NSUserDefaults` work – TomSawyer May 24 '16 at 10:17
  • @Lion i wonder speed of reading `NSUserDefaults` vs variables are the same or not? – TomSawyer May 24 '16 at 10:19
  • 2
    `NSUserDefaults` is used to *persist* data between app launches (user preferences at that) – it's not used to pass data about within your code. – Hamish May 24 '16 at 10:19
  • @originaluser2 I know, i use it like a constant. All i care is about memory + performance. You don't read the question? – TomSawyer May 24 '16 at 10:20
  • 2
    What do you mean "i use it like a constant"? Why not actually define a constant in code instead of `NSUserDefaults`? – trojanfoe May 24 '16 at 10:23
  • @TomSawyer I have read your question, although it's pretty unclear what you're actually asking. Clarifying your question with a concrete example would be helpful. – Hamish May 24 '16 at 10:23
  • `NSUserDefaults` and variables both are different thing. what you exactly asking? – Ketan Parmar May 24 '16 at 10:24
  • 2
    Accessing NSUserDefaults is slower than a variable, because a variable is stored in memory, whereas the NSUserDefaults is fetched from the disk. – binchik May 24 '16 at 10:25
  • 2
    If you asking about reading speed between variables and defaults then definitely you can read fast from variables. – Ketan Parmar May 24 '16 at 10:26

3 Answers3

11

NSUserDefaults persists its data on disk so at some point it must load that data from disk in order to store it in memory. It will need to write it back to disk when you tell it to synchronize.

Once in memory, it will store it in a dictionary-like container (probably NSMutableDictionary).

Reading from both disk is very expensive compared to reading a variable directly and reading from a dictionary is moderately expensive compared to reading a variable.

Reading/writing variables it much quicker by a long way.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • How do i know when it stored in memory? For example: i use `NSUserDefaults` to store setting of my app (a keyboard extension), now in the initialization, i call to `NSUserDefaults` to get all settings i want and store it to some global variables. The question is if i don't want to use that variables, should i use directly the value from `NSUserDefaults` ? Will it get better performance? My extension calls to the `NSUserDefaults` every single half second. It's a keyboard extension. So if user don't use, the process will not be killed. But after the `viewDidDisappear` i don't know what are left? – TomSawyer May 24 '16 at 10:32
  • 2
    I would store the data in variables (perhaps of a singleton class) and have methods to read from `NSUserDefaults` and write to `NSUserDefaults`, but only call that read/write method when something happens in the app lifecycle (i.e. going into foreground/background, etc.) – trojanfoe May 24 '16 at 10:34
  • Thanks, i'm doing that way, but the extension consumes much more memory thant i expected so i want to optimize it. But i don't really know about how iOS retains / release the memory with the extension. Why should i use singleton instead of global variables? – TomSawyer May 24 '16 at 10:40
  • I wouldn't have thought these variables would take too much memory. Using a singleton is a better pattern as you get the advantages of a normal class instance lifecycle (i.e. you can read `NSUserDefaults` in the `init` method, which would be private to the implementation). You can use global variables if you want, however you will need to keep a `isInitialized` state variable in order to know when to read `NSUserDefaults` into the variables. Singletons are just cleaner. – trojanfoe May 24 '16 at 10:43
  • @TomSawyer What are you saving? Twice per second, high memory footprint... doesn't make much sense to me. NSUserDefaults are not meant to store large things. And keeping its contents in local variable(s) shouldn't make the memory footprint any bigger than using the defaults (which will put them into memory anyway). Maybe there's some memory leak... – Eiko May 24 '16 at 13:41
  • Does this apply to keychain too? – Musa almatri Nov 25 '17 at 10:44
1

NSUserDefaults has a different use case than variables in your code.

The data is packed into a plist representation and needs to be stored to disk (well, at least when it gets synchronized), or read from disk (or from the cache, or some other implementation detail Apple sees fit). In any case, using the defaults should typically be much slower than using a simple variable. And the bigger the user defaults get, the higher the impact, as it will most probably store/read all of it every time. If it will matter in your use case is a different question that we cannot answer.

Use the approach that suits your needs: NSUserDefault to persist settings between application launches, and variables for normal operation. There's nothing wrong with having the settings cached in a local variable and only persisting changes (maybe not every time something changes).

Eiko
  • 25,601
  • 15
  • 56
  • 71
0

If you are worried that keeping data in variables takes memory, then you should use CoreData instead. You might also consider that NSUserDefaults will take memory :-)

NSUserDefaults is persistent storage. If you use it right, the data will be there again after your app crashes. Use it for things that you want to remember when your app runs the next time. Use variables for things that can start fresh when your app starts the next time.

gnasher729
  • 51,477
  • 5
  • 75
  • 98