I had the idea of adding a list feature in my app where users can create a list and add multiple recipes to the app so first and only thing I did was add an entity to my data model called "List" that contains a string: title and an array of Recipes: recipes (I remembered to put "NSSecureUnarchiveFromData" in Transformer and put [Recipe] for custom class). Afterwards I made the relationship in both entities and made them inverse.
I made no other changes to my code. But I ran it just to make sure nothing went wrong and lo and behold: 7 never before seen errors, but only in one file. Before adding this entity this same code compiled just fine. This is the file and these are the errors I'm getting. Any help would be greatly appreciated.
import SwiftUI
struct RecipeView: View {
@Environment (\.managedObjectContext) var managedObjContext
@Environment(\.dismiss) var dismiss
var recipe: FetchedResults<Recipe>.Element
@State var isFavorite: Bool
@State var servings = -1
var body: some View {
VStack(alignment: .leading){ //Error: Trailing closure passed to parameter of type 'CGFloat?' that does not accept a closure
if (recipe.notes! != ""){
Section{
Text(recipe.notes!)
.font(.headline)
}
.padding(.horizontal)
}
HStack{
Spacer()
Text("Total Time: "+calcTime(time:Int(recipe.totalTime!) ?? 0))
Spacer()
Text("Servings: "+recipe.servings!)
Spacer()
}
.padding(.vertical)
Grid{
GridRow{
Button {
isFavorite.toggle()
recipe.isFavorite.toggle()
PersistenceController().save(context: managedObjContext)
} label: {
HStack{
Image(systemName: isFavorite ? "star.fill" : "star")
.foregroundStyle(.yellow)
Text(isFavorite ? "Unfavorite" : "Favorite")
.foregroundColor(Color(UIColor.lightGray))
}
.frame(width: 300,height: 50)
.background(Color(UIColor(hexString: "#202020")))
.border(Color(UIColor(hexString: "#202020")))
.cornerRadius(5)
}
Button {
print("implement list functionality")
} label: {
Image(systemName: "plus")
.frame(width: 50,height: 50)
.background(Color(UIColor(hexString: "#202020")))
.border(Color(UIColor(hexString: "#202020")))
.cornerRadius(5)
}
}
}
.padding(.horizontal)
List{
NavigationLink(destination: ingredientsView(ingredients: recipe.ingredients!)){
HStack{
Text("List of Ingredients")
Spacer()
Text(String(recipe.ingredients!.count))
.foregroundColor(.gray)
}
}
.frame(height: 50)
NavigationLink(destination: instructionsView(instructions: recipe.instructions!)){
HStack{
Text("List of Instructions")
Spacer()
Text(String(recipe.instructions!.count))
.foregroundColor(.gray)
}
}
.frame(height: 50)
}
.listStyle(.grouped)
.scrollDisabled(true)
Spacer()
}
.navigationBarTitle(recipe.title!)
.navigationBarItems(trailing: shareButton)
.onAppear{
PersistenceController().updateDate(recipe: recipe, context: managedObjContext)
}
Spacer()
}
var shareButton: some View{
Button(action: {
print("Implement airdrop feature")
}){
Image(systemName: "square.and.arrow.up")
.foregroundStyle(.blue)
}
}
}
struct ingredientsView: View{
@State var ingredients: [String]
var body: some View{
List{ // Error: Trailing closure passed to parameter of type 'NSManagedObjectContext' that does not accept a closure
Section(""){
ForEach(ingredients,id: \.self){ String in
NavigationLink(destination:
NavigationView{
Text(String)
.frame(alignment:.center)
.font(.title)
}){
Text(String).lineLimit(1)
}
}
}
}
.frame(alignment: .center) //Error: Cannot infer contextual base in reference to member 'center'
//Error: Value of type 'List' has no member 'frame'
.cornerRadius(10)
.navigationTitle("Ingredients List")
}
}
struct instructionsView: View{
@State var instructions: [String]
var body: some View{
List{ // Error: Trailing closure passed to parameter of type 'NSManagedObjectContext' that does not accept a closure
Section(""){
ForEach(instructions,id: \.self){ String in
NavigationLink(destination:
NavigationView{
Text(String)
.frame(alignment:.center)
.font(.title)
}){
Text(String).lineLimit(1)
}
}
}
}
.frame(alignment: .center) //Error: Cannot infer contextual base in reference to member 'center'
//Error: Value of type 'List' has no member 'frame'
.cornerRadius(10)
.navigationTitle("Instructions List")
}
}
I would get rid of the 'recipes' attribute on your List entity. You traverse an NSManagedObject's relationships just like how you traverse attributes, so you can get the set of all of the recipes linked to a list like "myCurrentList.recipeList".
I would also change the name of the relationship from List to Recipe to instead be "recipes", but that's more a personal preference than a technical recommendation.
Edit: Just realized after posting that you have called one of your entities "List". You are also trying to use a SwiftUI construct named "List". They are conflicting. Rename your entity to something like "RecipeCollection", clean your build folder, rebuild, and they should no longer conflict.
This part was in my original post. It's wrong, but I'm leaving it for future readers, as it's good practice when making changes in Core Data. As for your errors, after you added the new entity and the new relationships, did you clean your build folder (Shift-Command-K) and rebuild from scratch? When updating Core Data's managed object model, it sometimes falls out of sync with Xcode's UI, which can lead to really weird errors. A clean and rebuild often gets you back to rational errors.