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.
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.