Skip to content

Instantly share code, notes, and snippets.

@rhysforyou
Last active March 4, 2016 01:25
Show Gist options
  • Select an option

  • Save rhysforyou/ca8d09c9350adeae3b85 to your computer and use it in GitHub Desktop.

Select an option

Save rhysforyou/ca8d09c9350adeae3b85 to your computer and use it in GitHub Desktop.

My Beefs With Realm

I've been working on an app recently using Realm's Swift SDK as my data store, and while it's leagues ahead of Core Data, I've run into some issues with it.

So in this app I've got a fairly large data set that's been localised into a bunch of different languages. To handle that, we replace any property on an object that needs to be localised with a list of objects that conform to a Localizable protocol. So let's say we have a Person object that looks like so:

class Person : Object {
  dynamic var name = ""
  dynamic var greeting = ""
}

In this case, a person's name is going to be the same in every country, but their greeting may vary, so we'd break that out into a new Localizable object like so:

protocol Localizable {
  var language: Language { get }
}

class Person : Object {
  dynamic var name = ""
  
  let greetings = List<Greeting>()
}

class Greeting : Object, Localizable {
  dynamic var greeting = ""
  
  dynamic var language: Language
  
  init(greeting: String, language: Language) {
    self.greeting = greeting
    self.language = language
    
    super.init()
  }
}

Now I want to make it so that given a list of Localizable objects, I can easily get the one for my current locale. In an ideal world, this would be something I'd implement asa protocol extension like so:

extension ListType where Element : Localizable {
  var currentLocaleObject: Element?{
    // Find an object for our current locale
  }
}

Then I could make that easily accessible on my model like so:

extension Person {
  var greeting: String {
    return greetings.currentLocaleObject.greeting ?? "fallback"
  }
}

However, Realm Swift doesn't define a ListType protocol, so protocol extensions are ruled out leaving me with no obviously good solution to this problem. My current solution is to define a free function that does the same thing, but it's far from ideal.

@jpsim
Copy link
Copy Markdown

jpsim commented Mar 4, 2016

Looks like you can do all of this using RealmCollectionType:

typealias Language = String

protocol Localizable {
    var language: Language { get }
}

class Person : Object {
    dynamic var name = ""

    let greetings = List<Greeting>()
}

class Greeting : Object, Localizable {
    dynamic var greeting = ""

    dynamic var language: Language = ""

    convenience init(greeting: String, language: Language) {
        self.init()
        self.greeting = greeting
        self.language = language
    }
}

let currentLocale = "en"

extension RealmCollectionType where Element : Localizable {
    var currentLocaleObject: Element? {
        return filter("language == %@", currentLocale).first
    }
}

extension Person {
    var greeting: String {
        return greetings.currentLocaleObject?.greeting ?? "fallback"
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment