print logo

How to convert a SQLite database to Realm (Swift)

Published: 2/17/2017 Author: Harkeerat Toor

Realm is the mobile database to use for those looking for a modern, fast, and off-line centric solution that works across all major mobile platforms. When you're starting from scratch, then it's easy to just dive in and get going. But sometimes you will have existing data that you need to convert over first. In this article, we will walk through on how you can accomplish this task with a little help from Xcode and Swift.

                                                                                        

The first thing you should do is check out the Realm Cocoa Converter. This is an officially supported solution designed by the Engineers over at Realm that can both import into and export from Realm databases. It currently supports CSV, XLSX, and JSON, with SQLite in their plans. If the converter doesn't support SQLite just yet, we will need to do it ourselves.

 

Creating the Realm Model Layer

Let's look at a simple SQLite Database and create the appropriate Realm model layer in Swift.

SQLite Database Structure:


Swift Model:

   
   
   
   
   
// Person model

class Person: Object {

    dynamic var id = 0

    dynamic var name = ""

    dynamic var birthdate = Date()

    let dogs = LinkingObjects(fromType: Dog.self, property: "owner")

    

    override static func primaryKey() -> String? {

        return "id"

    }

}

 

// Dog model

class Dog: Object {

    dynamic var id = 0

    dynamic var name = ""

    dynamic var breed = ""

    dynamic var owner: Person? // to-one relationships must be optional

    

    override static func primaryKey() -> String? {

        return "id"

    }

}


When creating Realm Model objects, for the most part the properties can be one-for-one matches of the column names in SQLite. But it's important to remember that Realm is not a relational database. And thus, it does not use foreign keys to create links between tables. To create these relationships, you must instead declare a property with the type of your Object subclass.

   
   
   
   
class Dog: Object {

…

dynamic var owner: Person?

This example will allow a Dog to have one owner as a Person Object. But these links are unidirectional, meaning while you can look at a Dog and see who the owner is, you can't view the a Person to see which Dogs it owns unless you create this inverse relationship. This can be done manually, but a less error-prone option is to use a property of LinkingObjects.

   
   
   
   
class Person: Object {

…

let dogs = LinkingObjects(fromType: Dog.self, property: "owner")

LinkingObjects will automatically add the property Dogs to Person. Any Dog that has the set as this Person will show up in this property. This allows for a one-to-many relationship as well, since LinkingObjects returns a RealmCollection which can be iterated through to navigate all the Dogs a Person owns.

Reading data from a SQLite database

Once your model is created, the next step is to read out the contents of the SQLite database. In Swift, a convenient library to do this is libsqlite3. Using this, you can create queries to read out the data from the SQLite, table by table.

        
   
   
   
   
let query = "select * from Person"

        

        // Open SQLite database

        var db: OpaquePointer? = nil

        if sqlite3_open(fileURL, &db) == SQLITE_OK {

            

            // Run SELECT query from db

            var statement: OpaquePointer? = nil

            if sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK {

                

                // Loop through all results from query

                while sqlite3_step(statement) == SQLITE_ROW {

                  …

                    }

                }

                

            }

            else {

                let errmsg = String(cString: sqlite3_errmsg(db))

                print("error running query: \(errmsg)")

            }

        }

        else {

            print("error opening database")

        }

Copying data to the Realm database

As you are looping through the results from SQLite, instantiate a Realm object and add copy the values over.

        
   
   
   
   
   
   
                  
// Create object for Realm

                    let realmPersonItem = Person()

                    

                    let id = sqlite3_column_int64(statement, 0)

                    print("id = \(id); ", terminator: "")

                    realmPersonItem.id = Int(id)

                    

                    let name = sqlite3_column_text(statement, 1)

                    if name != nil {

                        let nameString = String(cString:name!)

                        print("name = \(nameString); ", terminator: "")

                        realmPersonItem.name = nameString

                    } else {

                        print("name not found", terminator: "")

                    }

…

Once you are done, make sure to write the object as a transaction to the Realm database.

         
   
    
// Add to the Realm inside a transaction

                    try! realm.write {

                        realm.add(realmPersonItem)

                    }

Repeat for all the tables for your database.

Export Realm database file

Once the Realm database is complete, it is time to package and copy it for use in your mobile application. There is a default location where your Realm database is located, which you can find here:

         
   
    
let defaultRealmPath = Realm.Configuration.defaultConfiguration.fileURL   
   

Depending on your needs, you may want to create a compact version or encrypted version of the database for export. If so, you can use the writeCopy method to do just that. Now you will have a pre-initialized Realm database that can be used for all your mobile projects!

Where to go from here?

You can download a completed project of everything we walked through here. With your Realm set, you can get started using it by going through the official documentation.

If you have any questions or comments on this tutorial or mobile development in general, feel free to contact us.

 

 

 

 

Readiness_Assessment_Template_Icon<a href="http://ww.kieferconsulting.ontrapages.com/readiness">readiness</a>Readiness_Assessment_Template_Iconhttps://www.kieferconsulting.com/Banners/Readiness_Assessment_Template_Icon.png<a href="http://ww.kieferconsulting.ontrapages.com/readiness">readiness</a>

 

 

Building an Intranet That Your Users Love to Usehttps://www.kieferconsulting.com/BlogPosts/Pages/Building-an-Intranet-Your-Users-Love-to-Use.aspxBuilding an Intranet That Your Users Love to Use
A Checklist for Choosing a Cloud Service Providerhttps://www.kieferconsulting.com/BlogPosts/Pages/A-Checklist-for-Choosing-a-Cloud-Service-Provider.aspxA Checklist for Choosing a Cloud Service Provider
Three Ways to Get the Most Out of Your Office 365 Investmenthttps://www.kieferconsulting.com/BlogPosts/Pages/3-Ways-To-Get-Most_Out-Of-Office365.aspxThree Ways to Get the Most Out of Your Office 365 Investment
Making the move to Azurehttps://www.kieferconsulting.com/BlogPosts/Pages/Making-the-move-to-Azure.aspxMaking the move to Azure
3 Reasons Why You Need Power BI.https://www.kieferconsulting.com/BlogPosts/Pages/3-Reasons-Why-You-Need-Power-BI.aspx3 Reasons Why You Need Power BI.

 Recent Posts

CT Blog Post