Sometimes it is hard to know which technology to use in iOS for a specific task.
Storing data is indeed one of these cases. When I wrote my first app, a diet app for the Mac when the iPhone did not exist yet, I used Core Data to store its data (macOS and iOS share the same technologies and frameworks). Looking back, I think that was probably the right choice at the time, given the kind of data the app handled. But back then I had no idea and no way to tell. I picked Core Data just because I heard other developers talking about it and I didn’t know any other way. When it came to store static data in the app, though, I definitely made the wrong choice.
My diet app organized food and meals, performing other complicated calculations. Since entering new food and its nutritional values was time consuming, I wanted the app to come already with the most common food items. The problem was that I had no idea how to put this initial data in the app and Core Data did not seem to offer any functionality for that.
Not knowing anything better, I ended up with a self made terrible solution. First, I inserted all the data in the app myself manually, which took me a lot of time. Then, I hunted the Core Data storage file in the Mac system folders and copied it inside the app. Finally, I wrote code to open this file and copy data into the Core Data storage of the user the first time he started the app.
This was such a really bad solution that it cost me a lot of headaches and time. But there were actually better solutions I did not know at the time. Looking at the timeline of storage technologies in Apple’s operating system, Core Data was just the last one to be introduced. Before it existed, there were already many different solutions for saving data in apps. This is true for iOS too, and indeed Core Data did not come to iOS until its 3rd version. What I have realized though is that most developers don’t know about all these other options. Many often reach for the most complex ones (Core Data or SQLite) when there are much simpler solutions that would fit their needs.
For this reasons in this article I want to go over all the storage technologies available in iOS. We will look at when it’s better to use one instead of another, so that you can pick the right solution for your app.
Storing preferences and settings in the user defaults system
The user defaults system (commonly known as NSUserDefaults, which is the class used to access it) is the first option we will look into. This is one of the most known and maybe abused storage technologies in iOS.
- What to use it for: the user defaults system is intended to store the user preferences and the settings of an app.
- Advantages: user defaults are easy and immediate to use, since you don’t have to worry about how to access the file system, how to create and read files and which file format to use. User defaults can also be shared across devices through iCloud.
- Disadvantages: the space for user defaults is limited and they can be quite slow. This makes them practical only for small portions of data
- What not to use it for: although user defaults can store any kind of data, it’s better to use them only for preferences and settings and not to store other kinds of data. For those, use one of the other iOS storage technologies.
Read more on Apple’s Preferences and Settings Programming Guide
Remembering the state of the interface of an app with state preservation and restoration
When an iOS app is closed, it is possible to store the state of all the view controllers that are alive in that moment. In this way you can restore the UI the next time your app starts. (I explained in this other article how iOS view controllers represent the screens of an app)
- What to use it for: state preservation and restoration is useful to remember the exact state of the UI when an app closes. In this way you are able to restart the app in the same exact state the user left it the last time he used it, even when the app is terminated.
- Advantages: this system is specifically designed for remembering the UI state, so it works well with the view controller structure of your app
- Disadvantages: the preservation and restoration process can be tricky to understand and it’s error prone. This can lead to inconsistent states that can lead your app to crash often, especially when it starts. I have worked on some apps that would crash at every launch because of wrong handling of the restoration process.
- What not to use it for: state preservation and restoration uses Archives and coders (see more on these below), so the temptation might be to use this system to also store the data of the app along with itss state. This is not what this technology is meant for, use it only to store the state of the UI and use other solutions for the data of your app.
Read more in the state preservation and restoration section of Apple’s App Programming Guide for iOS
Storing hierarchical data in property lists
Property lists are a simple yet versatile storage technology on iOS that surprisingly many developers ignore (as I did for a long time)
- What to use it for: property lists work best with hierarchical data. But if you think about it, hierarchical data is very common in software development: XML, HTML and JSON are examples of hierarchical data. There are also many real life examples: a book can have chapters, which have sections, which have paragraphs. Xcode has also a dedicated editor for property lists that anybody can use. One example of a plist file is the Info.plist file that comes with any Xcode project.
- Advantages: the NSArray and NSDictionary classes provide methods that make writing and reading property list files very easy. This makes them an easy to learn and immediately available storage technology in iOS. The Xcode editor is useful to provide static data to an app and can also be used by non technical team members.
- Disadvantages: Although property lists can also store binary data, they are inefficient with large blocks of it. Property lists work best with data that takes only a few hundreds of kilobytes. Moreover, there is no mechanism to migrate data as your app evolves and their format changes.
- What not to use it for: If the data in your app is not hierarchical but has more complex relationship graphs, you should use other solutions, like Archives or Core Data. In the case of binary data (images, videos, music, etc.) you should write binary files directly to the file system.
Read more in Apple’s Property List Programming Guide
Storing files in the file system
In iOS, like in any other operating system, you have direct access to the file system, where you can create files and directories. The difference though is that iOS apps are sandboxed. This means that they can access only their own directories and have no access to system directories or to the ones of other apps.
- What to use it for: use the file system to property list files, binary data or documents, like text documents, spreadsheets, etc. The file system is also useful for temporary caches containing data that is expensive to generate or download. Some directories are also backed up and stored in iCloud.
- Advantages: the file system allows you to organize files in different directories, with different policies for back ups and iCloud. Some of these direcories can be used for temporary data and are flushed by the system when the space on the disk becomes low.
- Disadvantages: if you need to make more complex file operations like deleting, copying or moving, the file system is not as immediate to use as other technologies. It also requires you to understand how a file system works and to pay attention to the size and lifetime of your stored data.
- What not to use it for: if your app has data that does not fit into separate files and needs to be queried in different ways, Core Data might be a better choice.
Read more in Apple’s File System Programming Guide
Archiving and serializing data with coders and decoders
iOS includes a storage technology called Archives that few iOS developers know. Archives allow you to encode data with complex relationship graphs into a binary form throug the use of coders and decoders. You can then store this data in files or send it over a network. Nowadays there are better solutions, but it can still be helpful in some cases.
- What to use it for: use Archives to store data that has complex relationships and does not fit into a hierarchical structure like property lists. Nowadays there might be better solutions for your storage, but Archives are till used. Two examples in iOS where Archives are used are state preservation and restoration (see above) and interface files like xibs or storyboards. That is why views and view controllers have a required init(coder:) initializer.
- Advantages: Archives offer a fine grained control over how each instance in your objects graph is serialized and deserialized. This gives you flexibility when storing complex relational data, allowing you to exclude some or to avoid cycles. Archives in iOS also offer a versioning system to maintain compatibility with older versions of your data as your app evolves.
- Disadvantages: due to its flexibility, Archives are complex to learn and understand. Moreover it does not offer any querying capability, which you have to implement yourself.
- What not to use it for: Archives is not very popular among iOS developers, because with time other solutions were introduced. If your data is hierarchical, use property lists. For relational data where you need to be able to retrieve only parts of your data, use Core Data. Transmission of data over the network nowadays is usually done through JSON or XML. There might be cases though where all other solutions hit barriers and you might feel the need to roll out your own custom one. In that case, Archives might be a good starting point.
Read more in Apple’s Archives and Serializations Programming Guide
Managing data with complex relationships with Core Data
Despite what many iOS developers think, Core Data is not only a storage or database technology. In fact, storage is just a part of what Core Data offers. Core Data is a framework for object life cycle and object graph management.
- What to use it for: when the data in your app has complex relationships, where entities reference other entities in a complex relationship graph, Core Data is the right solution.
- Advantages: Core Data does not offer only storage, but has many other benefits, including undo management, partial data fetching, versioning and migration, iCloud synching and much more. It can also be used in document based apps.
- Disadvantages: given all it offers, Core Data is a complex beast to tame. Whole books and courses have been written over its complexities. Nonetheless, many apps do not need everything Core Data offers and end using only a limited subset of its functionalities.
- What not to use it for: if you need to store simple, structured data in your app, Core Data might be an overkill and you are probably better served by property lists. Moreover Core Data is designed to manage relational data. Even though it can contain binary data, it could be better to store it in the file system, where you can take advantage of directories and other policies for backing up and lifetime.
Read more in Apple’s Core Data Programming Guide
Managing a database with SQLite
Even though SQLite is not an iOS technology, it is available to use in iOS apps, so it is worth mentioning. SQLite is a database managements system.
- What to use it for: DBMSs are intended to manage data with complex relationships and offer a powerful querying system through the SQL language. There are cases in iOS apps where Core Data hits some limitations, often tied to performance. SQLite might be an alternative in those cases.
- Advantages: Like any DBMS, SQLite offers a powerful querying system that allows to retrieve and filter data and optimize queries. Moreover, SQLite might be a good solution in cases where cross platform compatibility is required, since it’s available on many platforms.
- Disadvantages: since SQLite is a DBMS, it requires learning the principles of database design (like the Entity-Relationship model) and querying (relational algebra). Moreover you have to learn SQL, the language used to manage tables and perform queries in relational databases. Moreover, since SQLite is cross platform, it has a C interface which is not very handy in Swift. But you can find open source Swift wrappers for this.
- What not to use it for: I am often surprised how quickly developers reach for SQLite when other solutions are usually better. We have seen all the ways you can store data in iOS in this article. For me, SQLite should always be the last solution you chose, when all the other ones fail to meet your needs.
Read more on SQLite’s website
[referral-form title=”Knowing how to store data is not enough when making professional iOS apps. Get my free course that covers the other fundamental parts” button=”Send me the FREE course”]
Matteo has been developing apps for iOS since 2008. He has been teaching iOS development best practices to hundreds of students since 2015 and he is the developer of Vulcan, a macOS app to generate SwiftUI code. Before that he was a freelance iOS developer for small and big clients, including TomTom, Squla, Siilo, and Layar. Matteo got a master’s degree in computer science and computational logic at the University of Turin. In his spare time he dances and teaches tango.