46
votes

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.
4
sqlite3 is more effectively for keeping large database, the search is more fast and it have many privileges.Viktor Apoyan
but does storing data in nsuserdefaults cause any problems when there is a lot of data? what priveleges does sqlite3 have?SEG
The first and main privelege is that you can sort, group, search very fast in sqlite3 databaseViktor Apoyan

4 Answers

16
votes

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
9
votes

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.

4
votes

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.

1
votes

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.