Search code examples
swiftrealmalamofireobjectmapper

Alamofire, Objectmapper, Realm: Nested Objects


I'm using Alamofire, Objectmapper, Realm and everything is working beside one thing: I can't map nested objects.

class Voting: Object, Mappable {

    dynamic var votingID: String = ""
    dynamic var question: String = ""
    var votingOptions = List<VotingOption>()

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

    func mapping(map: Map) {
        votingID <- map["id"]
        question <- map["question"]
        votingOptions <- map["votingOptions"]
    }

    override class func primaryKey() -> String {
        return "votingID"
    }   
}

class VotingOption: Object, Mappable{

    dynamic var optionID: String = ""
    dynamic var text: String = ""


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

    func mapping(map: Map) {
        optionID <- map["id"]
        text <- map["optionText"]
    }

    override class func primaryKey() -> String {
        return "optionID"
    }   
}

The JSON that I'm trying to map is:

{
    "Voting": [
        {
            "question": "Which option do yo prefer?",
            "id": "7f073efd-6f3d-43f2-9fe4-5cad683b77a2",
            "votingOptions": [
                {
                    "optionText": "Option 3",
                    "id": "3bc0a618-8791-4862-a7fd-5f2df464697d"
                },
                {
                    "optionText": "Option 1",
                    "id": "84c6a830-814b-40c8-a252-c074be5d689a"
                },
                {
                    "optionText": "Option 2",
                    "id": "8872ef6f-fc70-445a-802e-d39944006467"
                }
            ]
        }
    ]
}

The mapping funktion in VotingOption never gets called.


Solution

  • The old ListTransform solution no longer works in Swift 3.

    This is what I'm using now; put this in a file called, ListExtensions.swift, for example.

    import Foundation
    import ObjectMapper
    import RealmSwift
    
    /// Maps object of Realm's List type
    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)
            }
        }
    }
    

    This allows you to simply use it like this:

    class Parent: Object, Mappable {
        dynamic var id: Int = 0
        var children = List<Child>()
    
        required convenience init?(_ map: Map) {
            self.init()
        }
    
        func mapping(map: Map) {
            id <- map["id"]
            children <- map["children"]
        }
    }