Realm Tutorial: Getting Started
Learn how to use Realm, a popular cross-platform mobile database that is an alternative to Core Data. By Bradley Johnson.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Creating Your First Model
Open Specimen.swift from the Models group and add the following implementation:
import Foundation
import RealmSwift
class Specimen: Object {
dynamic var name = ""
dynamic var specimenDescription = ""
dynamic var latitude = 0.0
dynamic var longitude = 0.0
dynamic var created = NSDate()
}
The code above adds a few properties: name
and specimenDescription
store the specimen’s name and description respectively. Specific datatypes in Realm, such as strings, must be initialized with a value. In this case you initialize them with an empty string.
latitude
and longitude
store the coordinates for the specimen. Here you set the type to Double
and initialize them with 0.0
.
Finally, created
stores the creation date of the specimen. NSDate()
returns the current date, so you can initialize the property with that value.
Now that you’ve created your first model in Realm, how about using what you’ve learned in a small challenge?
Specimens will be separated into different categories. The challenge is to create a Category
model by yourself; name the file Category.swift and give your new model a single String
property name
.
If you want to check your work, the solution is below:
[spoiler title=”Category object”]
Once you’ve created a new Swift file Category.swift, its contents should look like this:
import Foundation
import RealmSwift
class Category : Object {
dynamic var name = ""
}
[/spoiler]
You now have a Category
model which you need to relate to the Specimen
model somehow.
Recall the note above that stated you could create relationships between models by simply declaring a property with the appropriate model to be linked.
Open Specimen.swift and add the following declaration below the other properties:
dynamic var category: Category!
This sets up a one-to-many relationship between Specimen
and Category
. This means each Specimen
can belong to only one Category
, but each Category
may have many Specimen
s.
You have your basic data models in place — it’s time to add some records to your database!
Adding Records
When the user adds a new specimen, they’ll have a chance to enter the specimen name and select a category. Open CategoriesTableViewController.swift. This view controller will present the list of categories in a table view so the user can select one.
Before you start writing code to integrate Realm into this view controller, you must first import the RealmSwift framework in this source file. Add the following line to the top of the file, just below import UIKit
:
import RealmSwift
You’ll need to populate this table view with some default categories. You can store these Category
instances in an instance of Results
.
CategoriesTableViewController
has a categories
array as a placeholder for now. Find the following code at the top of the class definition:
var categories = []
and replace it with the following lines:
let realm = try! Realm()
lazy var categories: Results<Category> = { self.realm.objects(Category) }()
When you you need to fetch objects, you always need to define which models you want. In the code above you first create a Realm
instance, and then populate categories
by calling objects(_:)
on it, passing in the class name of the model type you want.
try!
when calling Realm methods that throw an error. In your own code, you should really be using try
and do
/ catch
to catch errors and handle them appropriately.You’ll want to give your user some default categories to choose from the first time the app runs.
Add the following helper method to the class definition, below preferredStatusBarStyle
:
func populateDefaultCategories() {
if categories.count == 0 { // 1
try! realm.write() { // 2
let defaultCategories = ["Birds", "Mammals", "Flora", "Reptiles", "Arachnids" ] // 3
for category in defaultCategories { // 4
let newCategory = Category()
newCategory.name = category
self.realm.add(newCategory)
}
}
categories = realm.objects(Category) // 5
}
}
Taking each numbered line in turn:
- If
count
here is equal to 0 this means the database has noCategory
records, which is the case the first time you run the app. - This starts a transaction on
realm
— you’re now ready to add some records to the database. - Here you create the list of default category names and then iterate through them.
- For each category name, you create a new instance of
Category
, populatename
and add the object to the realm. - Finally, you fetch all of the categories you just created and store them in
categories
.
Add the following line to the end of viewDidLoad()
:
populateDefaultCategories()
This calls the helper method to populate your test categories when the view loads.
Now that you have some data, you’ll need to update the table view data source methods to show the categories. Find tableView(_:cellForRowAtIndexPath:)
and replace the method with the following implementation:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CategoryCell", forIndexPath: indexPath)
let category = categories[indexPath.row]
cell.textLabel?.text = category.name
return cell
}
This implementation retrieves a category from categories
based on the index path and then sets the cell’s text label to show the category’s name
.
Next, add this property below the other properties you just added to CategoriesTableViewController
:
var selectedCategory: Category!
You’ll use this property to store the currently selected Category
.
Find tableView(_:willSelectRowAtIndexPath:)
and replace the entire method with the following:
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath {
selectedCategory = categories[indexPath.row]
return indexPath
}
This will now store the user’s selection in the property you declared above.
Build and run your app.
Zoom and pan the map to somewhere interesting and create a new annotation by tapping on the + button in the top-right. Tap on the map pin to select it, and then tap on the annotation data to edit the details. Then tap the Category text field to see the list of categories as shown below:
You can select a category, but that will only save it to the property and not anywhere else in the database. It’s all well and good to see the categories show up in the app, but it’s always reassuring to actually see the records in the database. You can do this via the Realm Browser.