Search code examples
swiftrestkitrealm

How can I set same primary key in nested RLMObject with RKObjectMapping?


I want to set same primary key in nested RLMObject.
How can I set same id with RKObjectMapping?

firstly, I made following json file.
JSON file

{
  "id": 1
  "obj2": {
    "name": "name1"  
  } 
}

Secondly, I make following swift class file.
Class file

class Obj2: RLMObject {
    dynamic var id: Int <-- I want to set same id as Obj1.id
    dynamic var name: String!

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

    class func responseMapping() -> RKObjectMapping {
        let objectMapping = RKObjectMapping(forClass: self)
        objectMapping.addAttributeMappingsFromDictionary([
            "name": "name"
        return objectMapping
    }
}

class Obj1: RLMObject {
    dynamic var id: Int!
    dynamic var obj2: Obj2?

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

    class func responseMapping() -> RKObjectMapping {
        let objectMapping = RKObjectMapping(forClass: self)
        objectMapping.addAttributeMappingsFromDictionary([
            "id": "id"

        objectMapping.addPropertyMappingsFromArray([
            RKRelationshipMapping(fromKeyPath: "obj2", toKeyPath: "obj2", withMapping: Obj2.responseMapping())
        ])

        return objectMapping
    }
}

Solution

  • You would need to setup your mapping on the same JSON base object and not traverse the scope, which would make the mapping dependent on the relation.

    class Obj2: RLMObject {
        dynamic var id: Int
        dynamic var name: String!
    
        override class func primaryKey() -> String {
            return "id"
        }
    
        class func responseMappingForBeingOwnedByObj1() -> RKObjectMapping {
            let objectMapping = RKObjectMapping(forClass: self)
            objectMapping.addAttributeMappingsFromDictionary([
                "id": "id",
                "name": "obj2.name"
            ])
            return objectMapping
        }
    }
    
    class Obj1: RLMObject {
        dynamic var id: Int!
        dynamic var obj2: Obj2?
    
        override class func primaryKey() -> String {
            return "id"
        }
    
        class func responseMapping() -> RKObjectMapping {
            let objectMapping = RKObjectMapping(forClass: self)
            objectMapping.addAttributeMappingsFromDictionary([
                "id": "id"
            ])
    
            objectMapping.addPropertyMappingsFromArray([
                RKRelationshipMapping(fromKeyPath: ".", toKeyPath: "obj2", withMapping: Obj2.responseMappingForBeingOwnedByObj1())
            ])
    
            return objectMapping
        }
    }
    

    Some last words of warning: RestKit doesn't really support Realm at this point. So you may be better off with using something else for now, e.g. Realm's limited built-in support for decoding object representations, Realm+JSON or Decodable.