Module 4 Lesson 5 Recipe App Question

I have created an app much like this one but in my “Recipe” data, i have included a ‘summary’ property where it is an array of String:String - I have tried several ways to implement it in my Models ‘Recipe’ file. Chris has added a property ‘highlights’ which is an array of Strings but i don’t know how to implement this property, which looks like this in my json file within each Recipe:
“summary”: [
{“rating”:“5”},
{“serves”:“4”},
{“preparation”:“7 minutes”},
{“cooking” : “3 minutes”}
],
This information is to be used on the RecipesView page to display rating, servings, prep and cooking time but i don’t know how to implement in in the Recipe Model or parse it.
Any help would be appreciated.
FYI on what i have tried:

if i use: var summary: [String:String], i get this error:
typeMismatch(Swift.Dictionary<Swift.String, Swift.String>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: “Index 0”, intValue: 0), CodingKeys(stringValue: “summary”, intValue: nil)], debugDescription: “Expected to decode Dictionary<String, String> but found an array instead.”, underlyingError: nil))

if i use: var summary:[Summary],
then i add this class:
class Summary: Identifiable, Decodable {
var id: UUID?
var rating: [String:String]
var serves: [String:String]
var preparation: [String:String]
var cooking: [String:String]
}
i get this error:
typeMismatch(Swift.Dictionary<Swift.String, Swift.String>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: “Index 0”, intValue: 0), CodingKeys(stringValue: “summary”, intValue: nil), _JSONKey(stringValue: “Index 0”, intValue: 0), CodingKeys(stringValue: “rating”, intValue: nil)], debugDescription: “Expected to decode Dictionary<String, String> but found a string/data instead.”, underlyingError: nil))

Same error, either way

Please help

Set up your summary data in your json file like this:

        "summary": {
            "rating": 5,
            "serves": 4,
            "preparation": "7 minutes",
            "cooking" : "3 minutes"
        }

then set up your class for the summary properties like this:

class Summary: Identifiable, Decodable {
    var id: UUID?
    var rating: Int
    var serves: Int
    var preparation: String
    var cooking: String
}

then in your Recipe struct, change it to add the summary property :

struct Recipe: Identifiable, Decodable {
    var id: UUID?
    var name: String
    var featured: Bool
    var image: String
    var description: String
    var prepTime: String
    var cookTime: String
    var totalTime: String
    var servings: Int
    var highlights: [String]
    var ingredients: [Ingredient]
    var directions: [String]
    var summary: Summary  //  <------ Like this
}

(edit)
Your summary is not an array because each property is different. If each property name was the same then it would need to be an array.

1 Like

Hey Chris.

Thanks for the help with the Summary … I have 2 questions that i am hoping you can help me with.

  1. In Mod 4 - Recipe App - Chris shows us how to use Highlights but i don’t know how to implement the Summary rather than Highlights but in the same area. Can you show me? He does it in Lesson 13.

  2. I want to implement Categories as an option but i am not sure how to do it, I know i probably have to add a property in my json for ‘category: String’ but i don’t know how to implement this section in my project. Do you have an suggestions on tutorial i can follow?

Thanks,
Liz

Hi Liz,

Question 1

  • Where do you want to display the summary details? Maybe provide a screen capture of the View you want that detail to appear on and an indication of where you want to place those details. There are 4 properties in the summary to display so you need to think about how much data is in each field and what space is likely needed.

Question 2

  • I’m guessing that a Category is just going to be a name like “Sweets” or “Vegetarian” or “Entrée”. Is that what you are going to do? You could create a property in your struct as maybe var category: String
    In your JSON file you would have to add that as "category": "Vegetarian", for example and then go through each recipe in the json file and add the appropriate category.

Implementing it could be a simple as grouping the recipes by category and having a Section heading in the list view which would change as your scrolled down through all the recipes in each category.

Your JSON file (basing it on the Recipe App json file and taking into account what was discussed previously) might look something like this:

[
    {
        "name": "Eggplant Parmesan",
        "featured": false,
        "image" : "eggplant parmesan",
        "description": "Baked eggplant with bread crumbs and lots of cheese. Delicious!",
        "prepTime": "25 minutes",
        "cookTime": "35 minutes",
        "totalTime": "1 hour",
        "servings": 10,
        "summary": {
            "rating": 5,
            "serves": 10,
            "preparation": "25 minutes",
            "cooking" : "35 minutes"
        },
        "category": "Vegetarian",
        "ingredients": [
            {"name": "Eggplant, peeled and thinly sliced", "num": 3},
            {"name": "Large eggs", "num": 2},
            {"name": "Italian seasoned bread crumbs", "num": 4, "unit": "cup"},
            {"name": "Spaghetti sauce", "num": 6, "unit": "cup"},
            {"name": "Mozarella cheese, shredded", "num": 2, "unit": "cup"},
            {"name": "Parmesan cheese, grated", "num": 1, "denom": 2, "unit": "cup"},
            {"name": "Dried basil", "num": 1, "denom": 2, "unit": "teaspoon"}
        ],
        "directions": [
            "Preheat oven to 350 degrees F (175 degrees C).",
            "Dip eggplant slices in egg, then in bread crumbs. Place in a single layer on a baking sheet. Bake in preheated oven for 5 minutes on each side.",
            "In a 9x13 inch baking dish spread spaghetti sauce to cover the bottom. Place a layer of eggplant slices in the sauce. Sprinkle with mozzarella and Parmesan cheeses. Repeat with remaining ingredients, ending with the cheeses. Sprinkle basil on top.",
            "Bake in preheated oven for 35 minutes, or until golden brown."
        ]
    }
]

Hi Chris,

I have 5 tabs in my app:

  • Home (shows name of app, like a ‘About us’ view
  • Featured (just like in the tutorial)
  • Recipes List (shows a list view of all recipes)
  • Recipes - (all recipes shown in a different format (dribble)
  • Categores (to be shown by category)
  1. I am not too worried about the Summary as i am already showing them in a separate Recipes View

  2. The categories will be like Appetizers, Burgers, Salads, etc . I will add a category property in my Recipe struct, as well as, in my JSON, i will add: “category”: “Appetizer”.
    The main categories screen will show all categories in an image view inside a scrollview of some sort. If you click on Appetizer category, it takes you too all the Appetizers in a list view or scrollable list view (like the list view Chris did in the Module - Recipe App, but only category list views - this i don’t know how to separate)

Also, i don’t know how to:

“Implementing it could be a simple as grouping the recipes by category and having a Section heading in the list view which would change as your scrolled down through all the recipes in each category”

Any help would be appreciated.

Interpret that as meaning to sort the recipes by category so that when you display the recipes you will be able to set a Section header to be the category name and as you scroll through the list of recipes, that Section header will change as you scroll into the next category.

“Interpret that as meaning to sort the recipes by category so that when you display the recipes you will be able to set a Section header to be the category name and as you scroll through the list of recipes, that Section header will change as you scroll into the next category.”

I was a bit disappointed that Chris did not include this in the Recipe App tutorial as it is a major part of any Recipe app.

Keep in mind, i am new to this type of swift coding, so i am not sure how to do what you are saying. Can you show me how, in code, how i can do that and where in my CategoryView?
I would much appreciate that :slight_smile:

Liz

Realistically the Recipe course that Chris created is great. When creating a course I suspect you have to be careful to avoid “specification creep” so you have to draw the line at how complex you make it.

There are probably dozens of ways to make it more functional but the intent is to show how to decode JSON and present the data retrieved while covering some of the more commonly used techniques.

As far as code is concerned to list recipes in categories, have a look at this project I created which I hope will give you a bit of an idea how to do it.

1 Like

@Chris_Parker
I appreciate your help and i do understand what you are saying regarding the complexity of the app. You have helped me a great deal. Thanks again :blush:

From the example you shared - What does ContentView and ContentModel represent? I am assuming that ContentView represents CategoriesView?

@LizG

ContentView is the name of the default View that is generated when a SwiftUI project is created.

ContentModel is a class that conforms to ObservableObject in which you define properties that are Published. A Published item means that the Views that monitor that Published item will react to changes in the data inside that Published property and redraw the View.

If you followed the RecipeApp tutorial that Chris Ching created (I can’t remember if you said you did) you will remember that it has a RecipeViewModel which has the Published property recipes. In the sample program I provided the view model in that case is ContentModel. Perhaps I should have named it ContentViewModel.

So in the case of the sample program you will see that there are two Published items recipes and categories.
recipes is loaded from the the sampleData inside of the Recipe data model and categories is derived from the recipes data by looping through each of the records and adding the category to the array categories.

Hope that helps.

1 Like