iOS: How to save a custom object that is created in an app

14,278

Solution 1

The most powerful approach is to make your custom object a subclass of NSManagedObject, and store it in an NSManagedObjectContext using Core Data. On iOS this will always use an sqlite database, on Mac OS X you can use sqlite, xml, or a proprietary binary format (smaller/faster than xml).

Depending on how complicated your data structure is, and how likely it is to change in future, this technique may or may not be too complicated for your app. It's a lot of work to setup, and the API is very complicated, but it's the best choice if you need to store tens of thousands/millions of objects in a file.

For your app, I would have a single sqlite file containing all of the radio stations in the app.


The simplest option, is to implement the NSCoding protocol in your custom object's class. Documented here:

http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html#//apple_ref/doc/uid/20000948-BCIHBJDE

The basic theory is your object writes or reads all it's data to a "coder", and then passes the coder on to any child object(s). Outside of the class, you use an "archiver" or an "unarchiver" class to coordinate everything.

Once your custom class implements NSCoding you can read/write it to the disk with:

myObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
[NSKeyedArchiver archiveRootObject:myObject toFile:filePath];

This is a very simple approach, but it has a few drawbacks, for example you will need to figure out your own way to support different versions of the file format (perhaps with a different file extension for example).

Many classes in Cocoa/CocoaTouch already implement NSCoding, so they can be written to a file in this fashion (including NSArray, NSString, NSNumber, etc).

For your app, i would use this to store each radio station in a single file. When the app launches, load all the radio stations from a directory. You should consider enabling iTunes drag/drop filesharing for your app, so users can easily share radio station files with their friends or between devices.

This would also fit in well with iCloud for syncing between devices, I haven't looked into iCloud much, but I expect one file per radio station will be the ideal way to implement iCloud syncing.

Solution 2

There are three ways to persist data locally:

  1. Store objects in a database using managed objects or SQLite
  2. Store objects in a file in the sandbox using various classes' writeToFile
  3. Store the data in NSUserDefaults

How you persist your object data depends on how you're using it, and what type of data you're saving. CoreData makes sense if you have a lot of objects of the same type and SQL's search and sorting mechanisms would be useful. I tend to use the sandbox for very large files, eg images, sound files, and large agglomerations of data bounced through NSData. And I use UserDefaults for small amounts of data that might be considered "preferences".

You can put anything anywhere you want, and I suggest being familiar with all three mechanisms when you start a new project. Additional techniques, like using NSCoding to serialize and deserialize classes, can be used to make saving data easier. Note that once you've implemented NSCoding, you could store data anywhere and even send it over the wire.

For your RadioStation, I would personally use UserDefaults. The benefit of using NSCoding is that, once you implement initWithCoder and encodeWithCoder, you can stream a hierarchy of objects (eg an array of custom objects, each of which might contain a dictionary, array, or custom object, etc) fairly easily. If the only thing you're saving is an array of strings, then directly using UserDefaults is easy enough.

Share:
14,278

Related videos on Youtube

5StringRyan
Author by

5StringRyan

A native California Chicano, forged in the fires of Silicon Valley who is learning more about life in Colorado.

Updated on June 04, 2022

Comments

  • 5StringRyan
    5StringRyan almost 2 years

    I've been reading up on saving objects, preserving state etc, but I'm still a little confused on the route I should take when saving objects that are created from my app. I have built an app where a user can create a Radio Station with the Genre, name and frequency. Once a user hits save, a "RadioStation" object is created using a custom class and is stored in an NSMutableArray that is placed in the RootViewController. While RadioStation objects can be stored in this array and are displayed correctly in the table view, it's obvious that once the application quits, these are no longer going to be held by the application.

    At this point I'm not sure how I should begin to architect this design. Do I need to set up a plist? Should I use Core Data with a SQLite DB? Do I need to research iOS object serialization for both these scenarios? Or is there an more straight forward way that I'm not aware of?

    • Ben Zotto
      Ben Zotto over 12 years
      @Abhi: "Not really used" on iOS? Says who? I use them all the time. :) If you are talking about actual disk space usage, they're a great, low-overhead data format. They can be stored in a binary format. Just use NSPropertyListSerialization directly instead of the convenience methods.
    • Abizern
      Abizern over 12 years
      But there is a difference between saying "Plist files, and xml in general, are not really used on iOS" and then saying "I'd never use them"
  • Flyingdiver
    Flyingdiver over 12 years
    That doesn't work for custom objects. For custom objects, NSCoding is correct, per the above answer.
  • Abizern
    Abizern over 12 years
    You should have edited your original answer to add this extra detail rather than adding another answer.
  • Abhi Beckert
    Abhi Beckert over 12 years
    @Abizem they are two completely different answers, both valid approaches depending on details not provided in the question. Did you even read them?
  • Kev
    Kev over 12 years
    Please just use one answer, even if there are multiple solutions. Thanks
  • 5StringRyan
    5StringRyan over 12 years
    What would be the best directory to use for an iOS app to use for "filePath?"
  • AndrewS
    AndrewS over 12 years
    You can use NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); to get the path to your app's documents folder. Take a look at the document titled "Implementing Common Application Behaviors" for more information. Just concatenate that path with a slash and your filename and you'll get a filepath.
  • Floydian
    Floydian over 10 years
    writeToFile/arrayWithContentsOfFile are a very useful methods when you're working only with property list objects (developer.apple.com/library/ios/documentation/Cocoa/Concept‌​ual/…).
  • Ömer Faruk Almalı
    Ömer Faruk Almalı over 10 years
    @AbhiBeckert sir, you saved my day. thank you so much!