Search code examples
swiftrealmparent-childrelationships

Swift Realm - Creating child Realm objects and linking them to their parent


I am currently learning Realm and am converting my experimental app/game which uses arrays to Realm;

It loads pre-seeding data via a local JSON file and ObjectMapper; then creates objects in realm; this part seems to work.

// Parse response
let json = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as!  Array<Dictionary<String, AnyObject>>

let factories = Mapper<Factory>().mapArray(JSONArray: json)!
do {
    let realm = try Realm()
    try realm.write {
        for factory in factories
        {
            realm.add(factory, update: true)
        }
    }
} catch let error as NSError {
    print(error.localizedDescription as Any)
}

The issue I'm having is that when it maps; I'd like it to create its child objects at the same time and link them to parent.

Each parent (Factory) has about between 4 children (Engine) linked to it.

// Factory is parent object
class Factory: Object, Mappable {
    dynamic var name: String = ""
    let engines = List<Engine>()

    //Impl. of Mappable protocol
    required convenience init?(map: Map) {
        self.init()
    }

    // Mappable
    func mapping(map: Map) {
        name    <- map["name"]
    }
}


// Engine is a child to Factory
class Engine: Object {
    dynamic var production: Int = 0

   // create children and add to the parent factory
    static func createEngines(parent:Factory) -> [Engines]
    {
      var engines:[Engine] = [Engine]()
      for _ in stride(from:0, to: 3, by: 1) {
          //let engine : Engine = Engine.init(parent: element)
          //engines.append(engine)
      }
      return engines
    }
}

If I attempt to put this in my mappable

engines = Engine.createEngines(parent: self)

and make a change in my Factory model;

`var engines = List<Engine>()`

I get this error:

Cannot assign value of type '[Engine]?' to type 'List<Engine>'

The problem here is that simply creating an array of engines (children), appending it to an array doesn't seem to work with Realm and I'm not sure how to do this.

Hence, my question is how do I bulk create children, assign it to a given parent and add it to the current realm write/save?

Many thanks.


Solution

  • I changed my code to do this;

    1. Read all the factories from JSON
    2. Loop through the factories, creating engines
    3. Link the parent object up.

    I'm not sure if I did it right but it seems to be working.

    I just don't like how I'm having to hardwire the parent; as I thought Realm/ObjectMapper could do that for me. But its not a major issue as there is only about 3 or 4 relationships.

    let factories = Mapper<Factory>().mapArray(JSONArray: json)!
    
    do {
        let realm = try Realm()
        try realm.write {
    
            for f in factories
            {
                realm.add(f, update: true)
            }
    
            let factories = realm.objects(Factory.self)
            print (factories.count) // for debug purposes
            for f in factories {
                for _ in stride(from: 0, to: f.qty, by: 1) {
                    let engine : Engine = Engine.init()
                    engine.parent = f 
                    f.engines.append(engine)
                }
            }
        }
    } catch let error as NSError {
        print(error.localizedDescription as Any)
    }
    

    This above code seems to do the work for me; although I do wish I didn't have to manually set the parent (engine.parent = f)

    Anyhow, I've accepted @BogdanFarca's answer.