April 12, 2020

Getting Started with Realm Database for iOS in Swift

Getting Started with Realm Database for iOS in Swift

In this tutorial we will learn the basics of Realm Database, from installing it to building the models and writing the create, read, update and delete methods.

If you are looking for an in depth Realm Database tutorial, then this is not the article for you. I am looking to write some more focussed articles on Realm in the future. Once I do, I will link to them here.

Step 1: Adding Realm Database to your project

There are a few ways to installing Realm, but in this tutorial we will be using CocoaPods.

If you do not have CocoaPods installed you can install it by going to the root directory of your project and running the following command, sudo gem install cocoapods . I tried using the latest CocoaPods, which is 1.9.0 at the time of writing, but it did not work for me. If you run into the same issue you can use CocoaPods 1.6.0. To install 1.6.0 you can use the following command, sudo gem install cocoapods -v 1.6.0

After doing that you need to run pod repo update. This command will update CocoaPods so that is knows about the latest version of Realm.

Next you need to create a Podfile. To do this create a new file called Podfile in the root directory of your project. Add the following to your Podfile:

use_frameworks!
pod 'RealmSwift'

After adding the above to my Podfile, it looks like this:

# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'

target 'GettingStartedWithRealm' do
  use_frameworks!
  pod 'RealmSwift'
end

I updated my platform to iOS 11.

Once you have created your Podfile and added the code from above you need to run pod install in your root directory. By doing this CocoaPods will install Realm into your project.

Once it is installed you need to close your project if you have opened it with Xcode. CocoaPods requires us to use the xcworkspace file when opening the project and not the xcodeproj file.

Step 2: Import RealmSwift

I am going to be using the default ViewController file for this entire tutorial. If this was a real project I would split it up into different parts.

To import Realm into the ViewController, all we need to do is add the following import:

import RealmSwift

Step 3: Create the Models

When we are creating a model we need that model to be a subclass of Object. In this tutorial we will be creating a furniture store, so our two models will be Furniture and Store.

To create those two models, add the following to the ViewController file:

class Furniture: Object {
    @objc dynamic var name = ""
    
    static func create(withName name: String) -> Furniture {
        let furniture = Furniture()
        furniture.name = name
        
        return furniture
    }
}

class Store: Object {
    @objc dynamic var name = ""
    var furniture = List<Furniture>()
    
    static func create(withName name: String,
                       furniture: [Furniture]) -> Store {
        let store = Store()
        store.name = name
        store.furniture.append(objectsIn: furniture)
        
        return store
    }
}

The Furniture class has one property, name, and our Store class has two properties, the store name and a list of its furniture. Both models also have a create method which will allow us to create a new instance.

Step 4: Write to Realm

Now that we have our models setup, we can start saving data to our database. To write, we are going to create a simple method that will write data to our database. This write method will not take any parameters as it is for tutorial purposes.

Add the following method to your ViewController:

private func write() {
    let table = Furniture.create(withName: "table")
    let chair = Furniture.create(withName: "chair")
    let store = Store.create(withName: "Test Store",
                             furniture: [table, chair])
    
    // Write to Realm
    print("Write to Realm")
    try! realm.write {
        realm.add(table)
        realm.add(chair)
        realm.add(store)
    }
}

The above write function creates two Furniture instances, one being table and one being chair, we also created one instance of Store. When creating the table and chair we just provide it with a name, for the store we provide it with a name and we pass through the table and chair that we just created.

When we create these instances they are only in memory and have not been written to our database. To write it to our database we need to wrap the add method with try! realm.write as shown in the above code.

In Step 8 we will call all the methods that we are going to create. If we call it now it will save the above data every time the app runs.

Please note: In this tutorial we are force unwrapping try!, this means that if there is an error the app will crash. Please use the appropriate methods to safely do this in a production app.

Step 5: Read from Realm

We have our write method created. Which will allow us to write data to our database, now we need to read the data from the database. Once again, as with all these methods, they are just created for tutorial purposes. If one was going to write this for production we would want to be able to choose what to read, write, update and delete from the database.

But for now, let's create the read method. Add the following code below the write method:

private func read() {
    // Read from Realm
    print("Read from Realm")
    let data = realm.objects(Store.self)
    print(data)
}

All the above method will do is fetch the objects that we tell it to fetch. In the above code we pass through Store.self which will tell realm to fetch all the stores that we have saved.

At the moment we have not saved anything. But we will be saving stuff later on. For now, we can move on to updating data.

Step 6: Update existing data

In this update method we are going to read the first item of furniture in the database and we will update the name of it.

In our case, the first item of furniture will be the table because that is what we saved first in the write method. We have not called the write method yet, but we will call it in Step 8.

For now, we can add the update method below the read method:

private func update() {
    // Update data
    if let table = realm.objects(Furniture.self).first {
        try! realm.write {
            table.name = "New Table Name"
        }

        print(realm.objects(Furniture.self).first)
    }
}

The above code is a combination of our read and write methods.

In the code above we try and get the first Furniture item. It it exists, we will write it to realm by updating the property value inside try! realm.write.

After the value is saved, we will print out the first item of furniture. This will have the updated name.

Please note: In this tutorial we are force unwrapping try!, this means that if there is an error the app will crash. Please use the appropriate methods to safely do this in a production app.

Step 7: Delete data

The delete method is very similar to the update method.

Add the following code below the update method:

private func delete() {
    // Delete data
    print("Delete Data")
    if let tableToDelete = realm.objects(Furniture.self).first {
        try! realm.write {
            realm.delete(tableToDelete)
        }

        print(realm.objects(Furniture.self).first)
        print(realm.objects(Store.self).first)
    }
}

As with the update method, we will get the first furniture item that we have saved. If it exists, we will delete it. Realm has a delete method built in. To use the delete method we need to wrap it in try! realm.write as we would normally do when writing to the database or when updating the database.

After we have deleted the furniture item, we print out all the furniture items that are in the database and we print out the store. The store will now only have one furniture item.

Please note: In this tutorial we are force unwrapping try!, this means that if there is an error the app will crash. Please use the appropriate methods to safely do this in a production app.

Step 8: Calling the methods

Now that all of our methods have been created, we can call them. I have called all these methods from the viewDidLoad method. Update your viewDidLoad method to look like the following:

override func viewDidLoad() {
    super.viewDidLoad()
    
    self.write()
    self.read()
    self.update()
    self.read()
    self.delete()
}

If you build and run the app now, you will get something similar to the below output in Xcode console:

Write to Realm
Read from Realm
Results<Store> <0x7fb63275d8d0> (
	[0] Store {
		name = Test Store;
		furniture = List<Furniture> <0x600003f19560> (
			[0] Furniture {
				name = table;
			},
			[1] Furniture {
				name = chair;
			}
		);
	}
)
Optional(Furniture {
	name = New Table Name;
})
Read from Realm
Results<Store> <0x7fb63260b3e0> (
	[0] Store {
		name = Test Store;
		furniture = List<Furniture> <0x600003f1e250> (
			[0] Furniture {
				name = New Table Name;
			},
			[1] Furniture {
				name = chair;
			}
		);
	}
)
Delete Data
Optional(Furniture {
	name = chair;
})
Optional(Store {
	name = Test Store;
	furniture = List<Furniture> <0x600003f15b90> (
		[0] Furniture {
			name = chair;
		}
	);
})

This is the output from all the print statements that we added to the code. As you can see, we write the data. Once the data has been written, we will read the data. This will show us what is in our Store. As you can see, we have one Store that has two items of furniture.

Next we call update. The update method will update the name of the table furniture item. After we call update, we call read again to see the changes that have been made. When we call read it will print out our store again and we will see that the table that used be in the database now has the name New Table Name.

After the update we call delete. We deleted the first item of furniture, so we are expecting to only see the chair. As expected, when the delete method prints out all the furniture, all that is left is the chair.

We also see that when the delete method prints out the store, only the chair exists. So the store only contains 1 furniture item instead of 2.

Conclusion

And that is it! Realm is extremely easy to start with but the bigger question is should you use it? Would it be better than using Core Data? In most cases I personally prefer the tools that are created by Apple, but if Realm suits your use case best, then it would make sense to use it.

You can find the full source code here.