1

I have an app that will ideally compare luxury restaurants and their respective dishes against each other. This means I have a Core Data entity called Restaurant with attributes like restaurantName, location, averagePrice, and foodType. I have a second Core Data entity called MenuItem with attributes like foodName, caloryCount, price, and rating.

Since the goal is to compare, say, two steakhouses and their filet mignons on calories/price/rating, I'd really like to take a preloaded list of MenuItem objects I have (an array called selectedMenuItems) and somehow save that as an attribute of the Restaurant entity so that each individual restaurant will have an instance of those menu item objects attached to it (after which the user could edit the calories/price/rating for each menu item on a restaurant by restaurant basis). In the most ideal scenario, if anything was added or subtracted from the selectedMenuItems array of objects it would be reflected across all individual restaurants.

What I've tried so far:

1.) Many-to-many relationship between Restaurant and MenuItem

As you can probably guess from my above description, this didn't work out how I wanted it to since it only connected each restaurant to the selectedMenuItems array, and any alterations made in a restaurant propagated through the relationship to the array (this was a fundamental misunderstanding of relationships, on my part).

2.) Create an attribute of type Transformable in Restaurant to hold the selectedMenuItems array

This looked like it was going to work for a moment. As I said, I created an attribute called menuItems in my Restaurant entity of type Transformable, and then in the view controller for each restaurant's detail view (the view controller that displays the menuItems is an additional navigation step) I added the following inside of viewDidLoad():

// The selected Restaurant is passed from the prior screen to restaurant
restaurant.menuItems = selectedMenuItems as NSObject?

Which resulted in seemingly what I needed, except for the fact that if I made any changes to the selectedMenuItems array, it would cause the app to crash with the console readout 'NSInvalidArgumentException', reason: '-[Restaurant encodeWithCoder:]: unrecognized selector sent to instance.

3.) Break apart the selectedMenuItems array of objects into matched arrays of properties

After doing some experimenting with 2.), it appeared as though having an array of objects was the issue. Because of this, I iterated through selectedMenuItems and stripped out the properties into their own arrays (foodNameArray, caloryCountArray, priceArray, etc.). After that, I assigned each of those to newly created attributes of my Restaurant entity:

    restaurant.foodNames = foodNameArray as NSObject?
    restaurant.caloryCounts = caloryCountArray as NSObject?
    restaurant.prices = priceArray as NSObject?

Now, this was already looking very dodgy and prone to catastrophic failure. It did, however, work pretty much how I wanted it to. The issue here was that any changes to selectedMenuItems (like adding/removing a new object) didn't pass through to my restaurants after the first load. This is in contrast with 1.) where the changes propagated from the restaurants to selectedMenuItems (bottom to top) compared to 3.), where I want the changes to flow top to bottom.

Given the above descriptions, does anyone have advice on how I can get the functionality I'm looking for?

1 Answer 1

1

Rather than a many-many relationship, I would use three entities:

  • Restaurant, as you currently have;
  • Dish, which represents the generic menu item, such as "Filet mignon" or "Rib-eye"; and
  • MenuItem, which is a particular Dish served by a particular Restaurant.

Because Dish is generic, it would have only one attribute foodName (though you might want others). MenuItem would have attributes caloryCount, price, rating.

Since each MenuItem represents a particular dish served by a particular restaurant, it would have "to-one" relationships to Restaurant and Dish. For each relationship, the inverse would be "to-many": a Restaurant will serve many MenuItems, and a Dish could feature in many MenuItems.

You can then preload the list of Dishes, from which users can select those which are served by a particular restaurant. You can then create corresponding MenuItems and can presumably let users record calories/price/rating. If the user deletes a MenuItem, the corresponding Dish is unaffected, so will be available for other existing and/or new Restaurants. If the user wants to add a MenuItem for which there is no existing Dish, you can add a new Dish, which will then be available for any subsequent MenuItems.

Sign up to request clarification or add additional context in comments.

2 Comments

This sounds incredibly promising, thanks so much for the thorough answer! I will take a swing at this later tonight after work, and if it's functioning correctly I'll mark your answer as solving my issue.
I didn't have the time to fully set everything up and test, but I think this is exactly what I was looking for. You're a life saver, thanks so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.