Realm Blog

The Beginning of a Love Story with Realm 💘

Today’s blog post is by Genady Okrain, a developer in Israel addicted to making shiny apps, and is originally published on his blog. You can find Genady on GitHub and Twitter.

If you’d like to share your story about Realm, please email Tim!


Last week I was working on a new networking module that gets data using Rest API, the response is a JSON which represents a list of cities and each city has list of landmarks.

I wanted the data to be persistent (as cache) and have some kind of object representation. When I started to think about that problem I had few options to choose from. For the networking part I could go with the native NSURLSession or Alamofire - both are good options but the idea was to write less code, and Alamofire is built exactly for that mission with Rest API and JSONs. For the persistent database I had more options: Core Data, NSUserDefaults, Parse, FMDB and Realm - here again the idea was to write less code, try something new and built for Swift. I thought Realm will be easier to setup and wanted to see what is all the buzz around.

Eventually, I decided to use the two most used open source Swift frameworks and test them out.


Alamofire

It was pretty straight forward, added pod 'Alamofire' to my Podfile and sent that request:

Alamofire.request(.GET, url).responseJSON { _, _, JSON, _ in
...
}

 

The response is a list of cities with list of landmarks, I will use it for this example:

[
    {
        "name": "San Francisco",
        "landmarks": [
            {
                "name": "Golden Gate Bridge"
            },
            {
                "name": "Fisherman's Wharf"
            }
        ]
    }
]

More info: https://github.com/Alamofire/Alamofire


Realm

All you need to do to start using Realm in your project is add pod 'RealmSwift' to your Podfile, after that your objects look like that:

class City: Object {
    dynamic var name = ""
    dynamic var landmarks = List<Landmark>()
}

class Landmark: Object {
    dynamic var name = ""
}

 

Write example:

let city = City()
...
let realm = Realm()
realm.write {
  realm.add(city)
}

 

Read example:

let cities = Realm().objects(City)

More info: https://realm.io/docs/swift/latest/


Problem 1: List properties aren’t accessible from Objective-C

One to many relationship is probably something you are going to use, and probably you have at least one Objective-C file in your project too. Currently there is bug in Xcode that generates wrong bridging file that won’t even compile:

If you’re planning on using Realm Swift from Objective-C, you’ll have to make your List properties private or internal. This is due to a known Swift bug which causes the automatically-generated Objective-C header (-Swift.h) to be unable to compile. See GitHub issue #1925 for more details and suggested workarounds.

Solution

The workaround here is to make the List property to be private and expose it to the outside world with a function:

private let landmarks = List<Landmark>()
func _landmarks() -> List<Landmark> {
    return landmarks
}

More info: https://realm.io/docs/swift/latest/#current-limitations


Problem 2: Rest API to Realm objects mapping

This example is pretty basic but the real data is way complicated, I was trying to avoid writing this ugly block of code to parse the response:

if let cities = JSON as? [[String: NSObject]] {
    for city in cities {
        let city = City()
        city.name = city["name"] as! String
        ...
    }
}

 

Solution

The good news is that it is possible to use auto mapping, each key that matched to the Realm object will be mapped automatically:

let cities = JSON as! [[String: NSObject]]
let realm = Realm()
realm.write {
    for city in cities {
        realm.create(City.self, value: city)
    }
}

More info: https://realm.io/docs/swift/latest/#example


Problem 3: Support for null string

Turns out that null is a valid JSON value and with the automatic mapping of the previous section I found out that with the release version of Realm it is not possible to use String? as type:

Solution

Realm are working on adding that support and it is already possible to use beta version to solve it.

First, Switch to the ‘null-string-beta-2’ tag and add Realm pod to your Podfile too:

pod 'Realm', :git => 'https://github.com/realm/realm-cocoa', :tag => 'null-string-beta-2'

pod 'RealmSwift', :git => 'https://github.com/realm/realm-cocoa', :tag => 'null-string-beta-2'

Second, replace all the nullable String types to NSString?:

dynamic var name: NSString?

More info: https://github.com/realm/realm-cocoa/issues/628#issuecomment-106952727


The original post can be found on Genady’s blog, Unwrapped Swift. Thanks Genady!


Genady Okrain

Genady is a developer in Israel addicted to making shiny apps. He is currently working on a startup called Reelgood, and is the creator of several apps, including Strobe, Organizer, and the infamous app Parties for WWDC!

Get more development news like this