I am trying to display the data I get back from the firestore in my swiftUI app but am having some trouble.
Here is where I get the data
import Foundation
import Firebase
class RecipesViewModel: ObservableObject {
@Published var userRecipes = [RecipesData]()
func getData() {
// Get a reference to the database
let db = Firestore.firestore()
// Read the documents at a specific path
db.collection("Recipes").getDocuments { snapshot, error in
// Check for errors
if error == nil {
// No errors
if let snapshot = snapshot {
// Update the list property in the main thread
DispatchQueue.main.async {
self.userRecipes = snapshot.documents.map { d in
return RecipesData(id: d["id"] as? String ?? "", name: d["name"] as? String ?? "", cuisine: d["cuisine"] as? String ?? "", difficulty: d["difficulty"] as? String ?? "", dishType: d["dishType"] as? String ?? "", prepMins: d["prepMins"] as? Int ?? 0, prepHours: d["prephours"] as? Int ?? 0, cookMins: d["cookMins"] as? Int ?? 0, cookHours: d["cookHours"] as? Int ?? 0, restMins: d["restMins"] as? Int ?? 0, restHours: d["restHours"] as? Int ?? 0, likes: d["lkies"] as? Int ?? 0)
}
}
}
}
else {
}
}
}
}
and here is where the data gets stored
import SwiftUI
import FirebaseFirestoreSwift
struct RecipesData: Identifiable{
var id: String
var name: String
var cuisine: String
var difficulty: String
var dishType: String
var prepMins: Int
var prepHours: Int
var cookMins: Int
var cookHours: Int
var restMins: Int
var restHours: Int
var likes: Int
}
I can get the Data and if I choose to display the name of each recipe in a list I can do that.
But what I want to do is to have my data too like this when being displayed
import SwiftUI
struct AllRecipesView: View {
@ObservedObject var model = RecipesViewModel()
private var gridCollum = [GridItem(.flexible(),spacing: 0), GridItem(.flexible(),spacing: 0)]
var body: some View {
VStack{
LazyVGrid(columns: gridCollum, spacing: 0){
ForEach(model.userRecipes) {item in
overlayView()
}
}
}
}
init(){
model.getData()
}
}
struct AllRecipesView_Previews: PreviewProvider {
static var previews: some View {
AllRecipesView()
}
}
struct overlayView:View{
@ObservedObject var model = RecipesViewModel()
var body: some View{
ForEach(model.userRecipes) {item in
VStack{
VStack{
Spacer()
HStack{
HStack{
Image(systemName: "star")
.foregroundColor(.white)
.font(.system(size: 20))
Text(item.likes)
.foregroundColor(.white)
.font(.system(size: 15))
}
.padding(.trailing)
Text(item.prepMins)
.foregroundColor(.white)
.font(.system(size: 15))
.padding(.horizontal)
}
.padding(.bottom)
}
.frame(width:180,height:130)
.background(Color.red)
.cornerRadius(8)
.shadow(color: .black, radius: 3, x: 2, y: 2)
.padding(.bottom)
Text("Salmon and Rice")
Text("Some User")
}
}
}
init(){
model.getData()
}
}
But I keep getting error saying No exact matches in call to initializer
on the lines
Text(item.likes)
and
Text(prepMins)
How can I fix my errors please
CodePudding user response:
try something like this example code, using @StateObject var model = RecipesViewModel()
and passing it using @EnvironmentObject
.
To fix the errors you get, remenber Text()
needs a string, such as, Text(String(item.likes))
or Text("\(item.likes)")
.
struct AllRecipesView: View {
@StateObject var model = RecipesViewModel() // <-- here
private var gridCollum = [GridItem(.flexible(),spacing: 0), GridItem(.flexible(),spacing: 0)]
var body: some View {
VStack{
LazyVGrid(columns: gridCollum, spacing: 0){
ForEach(model.userRecipes) {item in
OverlayView()
}
}
}
.environmentObject(model) // <-- here
.onAppear {
model.getData() // <-- here
}
}
}
struct OverlayView:View{
@EnvironmentObject var model: RecipesViewModel // <-- here
var body: some View{
ForEach(model.userRecipes) {item in
VStack{
VStack{
Spacer()
HStack{
HStack{
Image(systemName: "star")
.foregroundColor(.white)
.font(.system(size: 20))
Text(String(item.likes)) // <-- here
.foregroundColor(.white)
.font(.system(size: 15))
}
.padding(.trailing)
Text(String(item.prepMins)) // <-- here
.foregroundColor(.white)
.font(.system(size: 15))
.padding(.horizontal)
}
.padding(.bottom)
}
.frame(width:180,height:130)
.background(Color.red)
.cornerRadius(8)
.shadow(color: .black, radius: 3, x: 2, y: 2)
.padding(.bottom)
Text("Salmon and Rice")
Text("Some User")
}
}
}
}