Cookcademy: Cannot call value of non-function type '[Recipe]'

Hello,

I am following the Swift course and am stuck with the Grids chapter on the Cookademy project.

I had errors in prior chapters I could research myself, as Xcode and Swift changed since the course material was introduced, but with this example I am stuck.

In the extension of the RecipesListView I am getting the error message

Cannot call value of non-function type ‘[Recipe]’

for this code piece

private var recipes: [Recipe] {
        recipeData.recipes(for: category)
    }

The whole extension goes as follows

extension RecipesListView {
    func recipes(for category: MainInformation.Category) -> [Recipe] {
        var filteredRecipes = [Recipe]()
        for recipe in recipeData.recipes {
            if recipe.mainInformation.category == category {
                filteredRecipes.append(recipe)
            }
        }
    }
    
    private var recipes: [Recipe] {
        recipeData.recipes(for: category)
    }
    
    private var navigationTitle: String {
        "\(category.rawValue) Recipes"
    }
}

Any help would be appreciated.
Kind regards

1 Like

I’m getting the same issue. Were you able to solve it?

I had the same issue. After comparing every line so far and trying to find a typo I gave up and downloaded the sample project.

There I saw, that the function seems to be incomplete in the article: There is no return statement at the end.

excerpt from the sample project code:

func recipes(for category: MainInformation.Category) -> [Recipe] {
        var filteredRecipes = [Recipe]()
        for recipe in recipes {
            if recipe.mainInformation.category == category {
                filteredRecipes.append(recipe)
            }
        }
        return filteredRecipes
    }

Edit: However, now I have the issue that the categories don’t get properly filtered. I just have all the recipes no matter what category I select.

After some further investigation i found the reason for my non filtered lists:

the func recipes never gets called. Studying the sample project I discovered that the ForEach condition within the body of RecipesListView had been updated:

var body: some View {
        List {
            //recipes in ForEach(recipes) refers to the func recipes; returns filteredRecipes 
            ForEach(recipes) { recipe in
                NavigationLink(recipe.mainInformation.name, destination: RecipeDetailView(recipe: recipe))
            }
            .listRowBackground(listBackgroundColor)
            .foregroundColor(listTextColor)
        }
        .navigationTitle(navigationTitle)

Might have been an oversight by me, but I didn’t notice the change in the articles of Cookcademy thus far.

The func recipes needs to be in the RecipeData ViewModel

class RecipeData: ObservableObject {
@Published var recipes = Recipe.testRecipes

func recipes(for category: MainInformation.Category) -> [Recipe] {
    var filteredRecipes = [Recipe]()
    for recipe in recipes {
        if recipe.mainInformation.category == category {
            filteredRecipes.append(recipe)
        }
    }
    return filteredRecipes
}

}

You will need to change the CookcademyApp to start at RecipeCategoryGridView()

@main
struct CookcademyApp: App {
var body: some Scene {
WindowGroup {
RecipeCategoryGridView()
}
}
}

Here’s what’s missing/wrong with the code as you follow along. When following along, you’ll hit a snag and see the error Cannot call value of non-function type ‘[Recipe].

Basically, recipeData is not a function, but a private var (private var recipeData: RecipeData), which is why XCode complains you’re calling a non-function. Once you call the actual function (func recipes(for category: MainInformation.Category) -> [Recipe] ), the code works as expected.

Change:

private var recipes: [Recipe] {
    recipeData.recipes(for: category)
  }

To:

private var recipes: [Recipe] {
        recipes(for: category)
    }

This will fix it, but then you’ll run into the error Missing return in instance method expected to return '[Recipe]' error, so you need to add return, which is not in any of the code samples:

extension RecipesListView {
    func recipes(for category: MainInformation.Category) -> [Recipe] {
        var filteredRecipes = [Recipe]()
        for recipe in recipeData.recipes {
            if recipe.mainInformation.category == category {
                filteredRecipes.append(recipe)
            }
        }
        return filteredRecipes
    }

Once that’s done, you can continue the exercise as normal.

1 Like

good fix. pretty terrible error there in downloadable ‘finished’ code.