46

Storing data permanently in an iPhone is usually done using Core Data or sqlite3. Most people prefer to user NSUserDefaults as a storage for application preferences, rather than using it as a normal database (such as sqlite).

I have found that large amount of data can be stored in NSUserDefaults, it is extremely easy to use and it is fast. So why not use this as a permanent storage? What are the limitations of NSUserDefaults as a database?

Update:
I frequently use three different ways of saving my data to disk.

  • Core data
  • Serializing objects to plists
  • NSUserDefaults

I do not use FMDB (or sqlite directly) anymore. What are the main advantages and disadvantages of each approach?

Some advantages of NSUserDefaults that I've come across:

  • Sorting, grouping, etc. can easily be done using NSPredicate.
  • NSUserDefaults is thread safe.
  • It takes one line to fetch and save data to NSUserDefaults.
SEG
  • 1,717
  • 1
  • 18
  • 33
  • sqlite3 is more effectively for keeping large database, the search is more fast and it have many privileges. – Viktor Apoyan May 30 '11 at 07:55
  • but does storing data in nsuserdefaults cause any problems when there is a lot of data? what priveleges does sqlite3 have? – SEG May 30 '11 at 07:58
  • 2
    The first and main privelege is that you can sort, group, search very fast in sqlite3 database – Viktor Apoyan May 30 '11 at 07:58

4 Answers4

16

Sqlite3 is more useful for keeping large database and to access to the database elements. You can sort the items of Sqlite3 database, you can search very fast for item in Sqlite3 dtabase. Sqlite3 database has many privileges that NSUserDefaults didn't have !


NSUserDefaults vs Sqlite3

NSUserDefaults is for user preferences, usually basic objects like NSString or NSNumber. Sqlite, serializing a collection of objects in a property list, or Core Data are all valid options for storing user data such as model objects you created.

You're not going to see a speed difference, but it's still best to pick the correct mechanism for what you're doing. If it's just preferences then use NSUserDefaults, otherwise I would serialize your objects to a plist. If you're new to Cocoa I would avoid Core Data and even Sqlite at first, to give yourself a chance to learn the basics first.


NSUserDefaults or Sqlite

When you want to store large amount of data with some relationship, go for Sqlite if you want to store less value go for NSUserDefaults. Sqlite occupies some memory so use it only you really need to save complex datas.


Using NSUserDefaults to save a lot of game data

Usually NSUserDefaults is used to save game settings. To save game data, it's usually better to use either SQLite or you could create a NSDictionary of objects and save to disk, here couple of post that may help:

  1. http://www.cocos2d-iphone.org/forum/topic/9308
  2. http://www.cocos2d-iphone.org/forum/topic/9210
Community
  • 1
  • 1
Viktor Apoyan
  • 10,655
  • 22
  • 85
  • 147
  • Not really. This is what i wanted to know. Thanks. – SEG May 30 '11 at 11:56
  • 1
    @ViToBrothers what if we store Dictionary in NSUserDefaults? – rptwsthi Jan 08 '13 at 05:52
  • @rptwsthi, that's the same question I have. I have an invoice and it has line items adding up to NSMutableArray. What Happens if I store it in NSUserDefaults? Is it good or bad? The line items may be 1 or 2 or may be even 100s of line items! O.o – Randika Vishman Apr 20 '14 at 17:54
  • 1
    @vishman we can store that much of data but that is never a good practice. You have always risk of data loss in case of application crash. – rptwsthi Apr 20 '14 at 18:13
  • :) Wonderful! The exact thing which I was thinking about!Thanks! I guess as in any case like which I have mentioned above, we should use temporally tables to store our data right?That's the only best practice!(CoreData or just pure SQLite implementation) My dream is to become a good iOS Engineer. That's where I started to wonder about these things! Your thoughts are appreciated! (y) – Randika Vishman Apr 21 '14 at 13:23
9

NSUserDefaults offers a trivial learning curve and thread safe implementation.

Otherwise I've found Core Data superior in every way. Especially with regards to configuring default values and migration routines.

Edit: As it turns out, NSUserDefaults "thread-safeness" seems to come from running operations on the main-thread. This caused severe frame-skipping in one of my applications; I ended up ripping out NSUserDefaults and replacing it with a thread-safe NSMutableDictionary which gets serialized to a file.

lorean
  • 2,150
  • 19
  • 25
  • Can I use Core Data as a Dictionary as I can with NSUserDefaults? As in storing values for keys? I honestly don't know much about Core Data. Is it possible for the saved data to be a hierarchical database like plists? Are there any good tutorials how to save some data in this way? – SEG Nov 12 '11 at 16:06
  • 1
    See section "User Info Dictionaries" http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMOM.html You can serialize an NSDictionary as NSData. So you could save an NSDictionary as an attribute to an entity. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html You could create a hierarchical database by just defining entities and relationships where the root level entity has no parent. – lorean Nov 14 '11 at 16:32
  • 1
    wish I could upvote more times - my app was plagued by occasional freezes for weeks and now the solution is obvious! How exactly is it "thread-safe" if data storage blocks the main thread?? very misleading – Cbas Feb 08 '16 at 19:15
4

For a project I am currently working on, I need to set up a big database (about 400.000 records). If you use NSUserDefaults you must add the Records which can take up to some minutes (depending on the device and how you import your data). If you use CoreData, you simply can copy a prebuilt Database to the documents directory of your app and use it immedeately.

That's why I rely on CoreData.

cem
  • 3,311
  • 1
  • 18
  • 23
1

One advantage of CoreData is that your object will be an NSManagedObject with properties. That means when you get or set the values you'll have autocomplete to help you out with the property names. It also makes for more readable code.

Meanwhile with NSUserDefaults, you have to use key-value accessors always, using strings for the key.

I.e.:

myGlobalSettingsObject.lastLoginTime = @(now);

vs.

[[NSUserDefaults standardUserDefaults] setValue:@(now) forKey:@"lastLoginTime"];

What if you accidentally make a typo in setting the key somewhere? Compiler won't warn you. What if someone puts in the wrong type somewhere? Compiler won't warn you.

E.g.:

[[NSUserDefaults standardUserDefaults] setValue:@"now" forKey:@"lastLoginTiem"]; ^ ^ ^^^^

... will cause neither warning nor error at build time... dangerous!

Other benefits of using an NSManagedObject would be that it can have validation; it can ensure non-null values; it can have custom getter and setter methods that you can use to do some cool stuff; it can handle automatic migration if you change something about how the values are all stored; and its data model becomes part of your repository, so you can easily track the history of changes to it.

Meanwhile, NSUserDefaults is quick and dirty, and great for basic little apps, but it is just very primordial. Fine for a small app, but if you have a huge app it will become difficult to manage compared to using Core Data.

The only possible thing about NSUserDefaults is that if your app needs to delete its CoreData store or you don't want to hassle with implementing thread-safe CoreData, it's lower maintenance in that regard.

CommaToast
  • 11,370
  • 7
  • 54
  • 69