Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm, Swift, Many-to-many relationship

Tags:

ios

swift

realm

On my API I've got a relationship between Stands and Products. In which stands have products, but products can be found in different stands aswell. I'm trying to replicate this relationship on my iOS-application, using Realm but I can't seem to get it working.

The goal of having this relationship is being able to search for Stands that sell particular products.

My model:

class Stand: Object {
    dynamic var id : Int = 0
    dynamic var name : String = ""
    dynamic var latitude : Double = 0.0
    dynamic var longitude : Double = 0.0
    let products = List<Product>()

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

class Product: Object {
    dynamic var id : Int = 0
    dynamic var name : String = ""
    let stands = List<Stand>()

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

When doing my API request for Stands I retrieve the associated Products with it aswell. When I append these to the Stands it works fine for my Stands model as the products are just normally added in the List().

But all of the products are individually created, without having any Stands attached to them.

Is there a way to directly assign these Stands to the Products upon creation of the Products? Just like it's happening the other way around?

My current solution is this..

func retrieveAndCacheStands(clearDatabase clearDatabase: Bool?) {
    backend.retrievePath(endpoint.StandsIndex, completion: { (response) -> () in
        let listOfProducts : List<(Product)> = List<(Product)>()

        func addProducts(stand: Stand, products: List<(Product)>?) {
            for product in products! {
                print(product.name)
                let newProduct = Product()
                newProduct.id = product.id
                newProduct.name = product.name
                newProduct.stands.append(stand)

                try! self.realm.write({ () -> Void in
                    self.realm.create(Product.self, value: newProduct, update: true)
                })
            }

            listOfProducts.removeAll()
        }

        for (_, value) in response {
            let stand = Stand()
            stand.id = value["id"].intValue
            stand.name = value["name"].string!
            stand.latitude = value["latitude"].double!
            stand.longitude = value["longitude"].double!
            for (_, products) in value["products"] {
                let product = Product()
                product.id = products["id"].intValue
                product.name = products["name"].string!
                stand.products.append(product)
                listOfProducts.append(product)
            }

            try! self.realm.write({ () -> Void in
                self.realm.create(Stand.self, value: stand, update: true)
            })

            addProducts(stand, products: listOfProducts)
        }

        print(Realm.Configuration.defaultConfiguration.path!)

        }) { (error) -> () in
            print(error)
    }
}

This stores the Stands and adds Products to them. It also creates all the products and adds 1 Stand per 10 ish Products (?).

I can't seem to figure out how to make this work. Does anyone else know how to solve this? Or a better solution?

like image 314
Alserda Avatar asked Dec 14 '15 21:12

Alserda


1 Answers

Instead of doing the double-bookkeeping necessary to maintain inverse relationships manually, you should use Realm's inverse relationships mechanism, which provides you with all of the objects pointing to another object using a given property:

class Product: Object {
    dynamic var id: Int = 0
    dynamic var name: String = ""
    // Realm doesn't persist this property because it is of type `LinkingObjects`
    // Define "stands" as the inverse relationship to Stand.products
    let stands = LinkingObjects(fromType: Stand.self, property: "products")

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

See Realm's docs on Inverse Relationships for more information.

like image 108
jpsim Avatar answered Oct 23 '22 04:10

jpsim