Skip to content

Instantly share code, notes, and snippets.

@danilValeev
Last active June 17, 2021 08:16
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save danilValeev/ef29630b61eed510ca135034c444a98a to your computer and use it in GitHub Desktop.
Save danilValeev/ef29630b61eed510ca135034c444a98a to your computer and use it in GitHub Desktop.
Easy mapping Realm's List and RealmOptional with ObjectMapper

This code helps using ObjectMapper with RealmSwift.

RealmSwift uses List<T> collection for "to many" relashionships and RealmOptional<T> for optional primitive types, but ObjectMapper can't map directly to List<T> and RealmOptional<T>.

With this operators you can properly define RealmSwift's relashionships and optional properties and use <- operator to map them.

Example

import Foundation
import RealmSwift
import ObjectMapper

class Chat: Object, Mappable {

    let messages = List<Message>()

    func mapping(map: Map) {
        // use <- operator to map a List
        messages <- map["messages"]
    }

    required convenience init?(map: Map) {
        self.init()
    }
    
}

class Message: Object, Mappable {

    dynamic var text: String? = nil

    let length = RealmOptional<Int>()

    func mapping(map: Map) {
        text <- map["text"]
        // use <- operator to map a RealmOptional
        length <- map["length"]
    }

    required convenience init?(map: Map) {
        self.init()
    }
    
}

Swift 3

import Foundation
import RealmSwift
import ObjectMapper

infix operator <-

/// Object of Realm's List type
public func <- <T: Mappable>(left: List<T>, right: Map) {
    var array: [T]?

    if right.mappingType == .toJSON {
        array = Array(left)
    }

    array <- right

    if right.mappingType == .fromJSON {
        if let theArray = array {
            left.append(objectsIn: theArray)
        }
    }
}

/// Object of Realm's RealmOptional type
public func <- <T>(left: RealmOptional<T>, right: Map) {
    var optional: T?

    if right.mappingType == .toJSON {
        optional = left.value
    }

    optional <- right

    if right.mappingType == .fromJSON {
        if let theOptional = optional {
            left.value = theOptional
        }
    }
}

Swift 2

infix operator <- {}

/// Object of Realm's List type
public func <- <T: Mappable>(left: List<T>, right: Map) {
    var array: [T]?

    if right.mappingType == .ToJSON {
        array = Array(left)
    }

    array <- right

    if right.mappingType == .FromJSON {
        if let theArray = array {
            left.appendContentsOf(theArray)
        }
    }
}

/// Object of Realm's RealmOptional type
public func <- <T>(left: RealmOptional<T>, right: Map) {
    var optional: T?

    if right.mappingType == .ToJSON {
        optional = left.value
    }

    optional <- right

    if right.mappingType == .FromJSON {
        if let theOptional = optional {
            left.value = theOptional
        }
    }
}
@artem-shmatkov
Copy link

@danilValeev, Thanks, really helpful!

@euroboy
Copy link

euroboy commented Jun 17, 2021

Getting an error: Reference to generic type 'Map' requires arguments in <...> after updating to Realm version 10.8.0

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