Category: Blog, iOS, Development

Why do we love Realm?

Why do we love Realm?

For many Core Data is a synonym for an iOS database. Mobile Core Data appeared in 2009 and for five years was the one and only solution. Nowadays Core Data in iOS 9 looks almost the same as the first from iOS 3 SDK. That makes it a little bit out-of-date, especially in Swift app. Fortunately since 2014 there is Realm – new king in the database kingdom.

Core Data was never an easy and nice framework. That’s why GitHub is full of wrapper frameworks like MagicalRecord, AlecrimCoreData or CoreDataStack. But it’s still the same old and not-so-fast Core Data.

According to the benchmarks Realm is from 5 to 30 times faster than Core Data. In addition it is much simpler than CD. Still not convinced? It’s open source and has dedicated version for iOS (Objective-C and Swift) and Android (Java). That means you can share databases and use the same high-level models across platforms.

Atlassian, Starbucks, McDonald’s, Alibaba and Virgin Mobile have trusted Realm and use it in their mobile apps. I believe it’s about time to abandon Core Data and switch to Realm. Don’t waste time and make a simple to-do app with Realm.

RealmToDo

That’s how the app is going to look like.

Right now you should have an almost empty project similar to default Master-Detail Application template. That’s a right place to make a new class which will store to-do task’s details. Make this simple and store only title, optional description and current status (do or done). Take a look at my Task class.

First of all, remember to import RealmSwift framework. Then notice that the Task is an Object subclass – Realm data model class.

All variables here are dynamic. That’s a Realm requirement for almost all (except List and RealmOptional) properties that can be stored in Realm. Well, that’s the best time for a few words about properties’ types used in Realm.

You can store Strings, Bools, all numbers (like Double, Float, Int and all its variations – in addition there is no need to typecast from/to a NSNumber like in Core Data), NSDates, NSDatas, other Objects (to-one relationship) and Lists of Objects (to-many relationship).

Elementary types’ optional properties can look weird at first glance, but they’re just fine. Just take a look at the cheatsheet and remember you can access a RealmOptional‘s value through a value property.

Back to the code. Probably you have noticed that I added date to Task class. That’s because we’re going to sort all tasks by date – recent tasks should be first.

All right, we’ve got a Task class. Now we should find a way to retrieve all tasks from a database. With Realm it’s really easy. Although let’s make some helper to make the code well-organised. That’s how my RealmHelper looks.

I made it generic, so new Object subclass won’t be a problem. Don’t be afraid of Results – it’s like an Array, but let you do for free some great things like using notifications.

Notice that according to Realm documentation you should never use Realm instance as a singleton – that can occur in many hard-to-solve thread issues. Now you see why I prefer helper like this – every single task for objects creates Realm instance and then returns what you want.

Don’t worry about performance or issues about objects from two or more returns – there is plenty of magic here and Objects are auto-updating. Please take a look at the example in the documentation.

We can retrieve tasks, but still we can’t save, update or delete them. Let’s write an extension for Object, but still remember about Realm instances logic.

We’ve got all database business ready. Before check it out let’s talk about UI logic behind the app.

I decided that MasterViewController‘s table view should show all tasks – unfinished recent first. A cell selection should open a DetailViewController which allows edit task’s details. Add button should push a DetailViewController. Cell’s swipe should allow to remove cell’s task. Let’s do it one by one.

Tasks in table view

We should have all tasks in MasterViewController, so add this at the top of the class.

That retrieves all objects, but as I said, I prefer unfinished recent tasks first. Realm loves chaining, but don’t try sorted(_:).sorted(_:) – it won’t work as expected. Instead try something like this:

First sort by done and then by date property. You’ve got to be careful here – properties’ names are just strings.

Don’t forget about UITableViewController‘s delegate methods. These set number of rows and section right.

Cells should look different for done and to do tasks. Strikethrough and gray text color for done should be all right. We can achieve this by attributedText and textColor properties.

DetailViewController is going to let each task be changed. We’ve got to cover this in MasterViewController. Each task update should be visible in the main view controller. The easiest way to do that is using Realm notifications.

First, we need a property that stores NotificationToken. Then we should add notification block for objects we have. It should look like this:

The notification stays active as long as a reference is held to the returned notification token. You should hold onto a strong reference to this token on the class registering for updates, as notifications are automatically un-registered when the notification token is deallocated.

Removing tasks

It’s quite easy and can be done through these two delegate methods.

Add button

In this case insertNewbutton(_:) always executes a segue. So we’ve got to override prepeareForSegue(_:sender:) method. If there is any selected row then we should pass it to the detail view controller. First, we should add a task property to the DetailViewController:

Then go back to MasterViewController and be prepared for the segue.

Task details

We should show all details in a DetailsViewController. viewDidLoad() seems to be a right place.

Add this at the bottom of the func’s body.

Last, but not least. We should save all the changes to the task object when Save button is pressed. If we’re adding new task, then should execute add() on it. When updating an elder one, we should do it in an update block. Then return to the previous view controller. Take a look at my approach of this.

A saveObject() is a saveButton‘s action. If there is a task, it just executes updateTask(_:) on it. If there is no task, then before updating, it creates and saves one. Of course all properties can be fulfilled before saving the task, but that makes part of the code reusable.

That’s all!

It wasn’t so hard, was it? 🙂 I hope you’re convinced to Realm now. It’s efficient in little projects like this, but also in bigger ones.

Thank you for reading and remember that you can find all the source code on our GitHub repository mentioned at the beginning.

About the author

Piotr Sochalewski

Piotr Sochalewski

Droids On Roids iOS Developer