Search code examples
swiftuicore-dataargumentsparameter-passing

Trying to figure out my error for "Missing argument for parameter 'plans' in call; Insert 'plans: <#Plans#>'"


New to SwiftUI and have searched everywhere to figure out what I think is a simple problem. So I'm turning to the community for help or education please. Any help is very appreciated and will help me get unstuck.

I know the error is thrown because my row is expecting some type of value passed to it, but I can't figure out what the value it wants is.

I'm trying to pull data from Core Data and format it in rows with data from an array so the user can view their itinerary.

import SwiftUI
import CoreData

struct IteneraryView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Plans.date, ascending: false)], animation: .default)
    
    private var listPlans: FetchedResults<Plans>
    
    //Date formatter
    var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateStyle = .short
        return formatter
    }
    
    //Ability to group entries
    func groupedEntries(_ result: FetchedResults<Plans>) -> [[Plans]] {
        return Dictionary(grouping: result) { (element: Plans) in
            dateFormatter.string(from: element.date!)
        }.values.sorted() { $0[0].date! > $1[0].date! }
    }
    
    var body: some View {
        NavigationStack {
            //TRY THE UPDATED FETCH CODE HERE
            List {
                ScrollView {
                    ForEach(listPlans) { plan in
                        RowView() //<<THIS IS WHERE I GET THE ERROR; IT WANTS plans: <#Plans#>?

                    }      
                }
            } //List
            .navigationBarTitle(Text("My Itenerary"))
        } //NavigationView
        .dynamicTypeSize(.xSmall ... .xxxLarge)
        
    }
    

Here is the RowView

import SwiftUI
import CoreData

struct RowView: View {

    let plans: Plans
    
    var body: some View {
        HStack(alignment: .top) {

            VStack(alignment: .leading, spacing: 2) {
                Text(plans.showTitle)
                    .bold()
                Text("\(plans.showDate, style: .date)")
                    .font(.caption2)
                //Spacer()
            }.padding(.top, 5)
            Spacer()
        }.padding(.top, 5)
    }
}

//struct RowView_Previews: PreviewProvider {
//    static var previews: some View {
//        RowView(plans: Plans)
//    }
//}

And the Extenstions

I have a core data Entity called Plans with "title" and "date"

import Foundation
import SwiftUI

extension Plans {
    
    var showTitle: String {
        return title ?? "Undefined"
    }
    var showDate: Date {
        return date ?? Date()
    }
}

I'm attempting to allow the user to select an event from a list, they show that event on their itinerary as a row, along with the district and city.

import SwiftUI
import Foundation


class UserSelections: ObservableObject {
    @Published var selectedRide = ""
}

struct Event: Identifiable {
    let id = UUID()
    var index: Int
    var name: String
    var district: String
    var city: String
}

var events = [
    Event(index: 1, name: "Concert", district: "Power and Light", city: "Kansas City"),
    Event(index: 2, name: "Museum", district: "Art", city: "Kansas City"),
    Event(index: 3, name: "Grand Central", district: "Downtown", city: "Kansas City"),
]

But I can't figure out what that pesky RowView wants me to pass to it. Any help is greatly appreciated on my learning journey.

I thought I could just pass RowView(plans: plans) but it doesn't like that. I tried passing Plans() and that seems like it works, but then crashed the preview. I also tried

RowView(plans: <title: "Event", date: Date()>)

But I don't want to pass that permanent info in (plus it doesn't work anyway).

I feel like I've tried every combination of Plans, Title, and Date, and XCode doesn't like any of it. Thanks again.


Solution

  • This is a Swift issue, not really related to Core Data or SwiftUI. Your RowView includes this:

    let plans: Plans
    

    If a Swift struct includes a let declaration, you must provide a value for that when you create an instance of the struct. In this case, you can't call RowView() because that doesn't include a value for plans. You have to call it as RowView(plans: [put some instance of Plans here]).

    This is the rule for any Swift struct with a let property. You can read more about Swift initialization rules in Apple's Swift language guide.

    In this specific case, since you're filling in the scroll view with ForEach(listPlans) { plan in .... }, I think you need to change RowView() to read RowView(plans: plan). That way you're passing the plan from the ForEach into the RowView initialization.