I am trying to get all records from Coredata Entity 'Location' and pull the data from the entity to create an array of strings and display in a MenuPicker. In getLocationNames() ForEach statement it never pulls locations even though there are records. Also I do have a warning on that line: Result of 'ForEach<Data, ID, Content>' initializer is unused. How to fix this?
struct WeatherView: View {
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.presentationMode) var presentationMode
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Location.locationName, ascending: true)],
animation: .default)
private var locations: FetchedResults<Location>
@State private var locationNames: [String] = []
@State private var locationDetails:[String] = []
@State private var selectedLocation: String? = nil
@State private var location: Location? = nil
var body: some View {
NavigationView {
ScrollView (showsIndicators: false) {
HStack {
Text("Select Location")
Picker("Location", selection: $selectedLocation , content: {
ForEach(locationNames,id: \.self, content: { locationName in
Text(locationName )
})
})
.pickerStyle(MenuPickerStyle())
.onReceive([self.selectedLocation].publisher.first()) { value in
selectedLocation = value
print("selectedLocation: \(selectedLocation ?? "not found")")
}
.onTapGesture {
self.getLocationNames()
}
}
header: {
Text("**Current **")
.padding(.top, 10)
}
}
.navigationTitle("Locations")
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("Detail", action: { onAdd()
} )
.foregroundColor(.blue)
}
}
}
.onAppear{
self.getLocationNames()
}
}
func getLocationNames() -> (Void){
ForEach(locations) { location in
let locationStr = self.getLocationString(location: location)
}
}
private func getLocationString(location: Location) -> String {
var locDetails: String = location.locationType! + "; "
locDetails += location.locationName! + ", "
locDetails += location.zip!
locationNames.append(locDetails)
return locDetails
}
}
In SwiftUI, ForEach
is a view builder, so it only makes sense and works as part of a View
. The first problem here is that you're calling ForEach
in a function that returns Void
, so you're using something that builds views but then throwing the result away by not using it anywhere. That's what the error message is telling you-- You used ForEach
to create views, and the function code would return the views, but you're not doing that because you return Void
.
The second problem is that ForEach
is a view builder-- so the closure inside it needs to return View
s. Only you're not doing that-- you're assigning a value to a local variable called locationStr
, which don't use for anything. You need to create a View
of some kind in that closure. You might want to use locationStr
in a Text
or a Label
or something else, but you need to create some kind of View
in there for ForEach
to do anything useful.