Saving Data on Mobile

I’m currently building some iOS apps and exploring various options for storing user data. I’ve summarised my findings here.


JSON is a popular structured representation of data like this:

  { "name":"iPhone 12", "capacity":"64GB" },
  { "name":"iPhone 12 Pro", "capacity":"128GB" },
  { "name":"iPhone 12 Pro Max", "capacity": 128GB" },

Human Readable Data Format

JSON can usually written straight to a file on a the device. Because it’s just text, you can also store JSON in a SQL database as a field. Its simplicity makes it easy to send/receive between devices and its high readability makes it easy to edit and make updates to the data, without requiring any specific knowledge or tools.

Its hierarchical data structure means JSON naturally maps to data structures (objects) used in code.


A popular SQL database that lets you perform CRUD (create, read, update, delete) operations on 1 or more tables of data. Relationships can be specified between columns. For example, you could have Customer, Product, and Order tables, and Orders has Customer and Product columns keyed to the customers and products held in their respective tables, storing orders of products by that customer.

Faster Querying, Less Code

SQLite has a major advantage over JSON in that the data is queryable. Instead of writing code to scan the entire list of items as you normally would with JSON files to check each field on each item, in SQLite you can simply do a quick query on the data you want. For example “SELECT all iPhones with capacity of 128GB”. This reduces the amount of code you have to write, as well as being faster, as a SQLite database can use optimised algorithms and indexing to retrieve that data as quickly as possible.

Compared to JSON files, SQLite does however require special tools and APIs to read and make changes to the database – it’s not as simple as editing a file directly as you would with JSON in a text editor.

Another thing to be aware of is that you may still need extra code to map the results of SQL queries to the data structures (objects) you’re using in your app.

Core Data

This is Apple’s out-of-the-box solution for storing data in iOS apps. It enables you to specify an object graph – for example objects representing Customer, Product, and Orders, and the relationships between them, and then run standard CRUD operations on this data set.

One advantage of Core Data over just SQLite is that it can be easier to use, with visual tools (in this case Xcode) enabling a developer create objects and specify options (e.g. whether the field is required) and relationships between objects, without needing to know how to structure a SQL database and do manual queries on it.

Core Data is a higher level of abstraction that still uses a lower level technology like SQLite to do the actual storage and manage underlying tables of data.

The downside of Core Data is that it can add unnecessary abstraction and complexity – if you’re comfortable just working with a SQLite database or JSON file directly to read/write a simple list of data items, then building and maintaining an object graph layer is likely to be overkill.

On the other hand, if you’re going to be creating model objects from your data anyway, then using Core Data can help mitigate unnecessary extra work as these models can be generated from the data scheme automatically.

Lack of Portability

It’s hard to transplant user data stored in Core Data from an iPhone device to an Android device, as Android doesn’t have a Core Data API. The underlying SQLite database is not in a format that’s easy to decipher directly and requires considerable work to translate into another format such as JSON before it can be exported for use elsewhere. It also adds an additional point of failure – for example Apple recently deprecated Core Data iCloud sync which means that developers that chose Core Data for its automatic sync capabilities may no longer be able to rely on sync to work, as well as being stuck with a more complex data stack that’s now harder to migrate elsewhere.

iCloud Drive

On Apple devices, an app can store files (such as JSON files) in the user’s iCloud Drive folder.

This has the advantage of making the file accessible to the user. In the JSON file example above, the user can add another iPhone product themselves (by opening, editing and saving the JSON file in their iCloud Drive, using a text editor). The App using that JSON file can then pick up those changes. The user can also backup/restore the JSON file themselves, and generally has more control of their data.


This is a simple lightweight dictionary available in iOS apps that lets you store small amounts of user data, such as settings and preferences. UserDefaults is based on XML, and not suitable however for larger sets of data, such as lists of thousands of products or orders. It isn’t easily queryable like a SQLite database, and is slower and takes more memory for large data sets. Nor is the UserDefaults XML file format as easily editable or transferrable as a JSON file.

If the UserDefaults file grows very large with lots of entries (e.g. 1000+ entries or 1MB+ in size), it’s worth remembering that it needs to be destroyed and recreated each time it is updated, which could get slow.


Keychain is a dictionary, similar to UserDefaults, and is a system-level service provided by iOS to typically store login/password and other security-sensitive details. When a password is automatically filled-in, this data usually comes from a previously populated keychain.

Unlike UserDefaults, Keychain data isn’t just an XML file that can be opened/changed easily, so is more secure. Data stored in Keychain is stored at the OS level, not inside the app folder, so it can stay on the device even if the app is removed. An app’s keychain data is not accessible from other apps.


Comma-separated values (CSV) is a popular format for tabular data – for example many online banks will let you download your transactions in CSV format so you can open and edit them in spreadsheet software like Microsoft Excel. CSV is simply a list of comma-separated values such as below:

"iPhone 12", 64GB,
"iPhone 12 Pro", 128GB,
"iPhone 12 Pro Max", 128GB

Each entry is separated by a new line. The downside of CSV is that it’s brittle and lacks keys describing each value (a problem which JSON solves). This means an app that relies on a specific structure in the order of the data could crash if the column order changes, or a new unexpected field is added, and any bugs created can be harder to diagnose because unlike JSON it may not be immediately apparent what’s missing or unexpected in the given data.

CSV may be suitable for some sorts of tabular data that is unlikely to change in format. For data structures that are hierarchical (or may become so) JSON is is clearly a better choice, especially when the JSON maps to a data structure/class that will be represented in code.

Further Reading