I am trying to populate a view when a button is tapped on a different view. When I used my mock data, everything worked fine. However, when I switch to calling my firestore db data, nothing shows up. I’m still a few months into learning swiftui but I called on db the same way in a different part of my project which worked well. Here is an example of the code I am using.
import SwiftUI
import FirebaseFirestore
import FirebaseFirestoreSwift
struct RewardsView: View {
// Dummy Data
// var rewardItems: [Reward] = [
// .init(RewardText: "10% Off Next Haircut", RewardRedeemed: false, rewardPhoto: "crown_kings_main_photo", costOfReward: 10),
// .init(RewardText: "10% Off Extra Service", RewardRedeemed: true, rewardPhoto: "crown_kings_main_photo", costOfReward: 8),
// .init(RewardText: "20% Next Haircut", RewardRedeemed: false, rewardPhoto: "crown_kings_main_photo", costOfReward: 15),
// .init(RewardText: "30% off Next Haircut", RewardRedeemed: false, rewardPhoto: "crown_kings_main_photo", costOfReward: 20),
// .init(RewardText: "25% Off Next Haircut", RewardRedeemed: true, rewardPhoto: "crown_kings_main_photo", costOfReward: 18),
// .init(RewardText: "45% Off Next Haircut", RewardRedeemed: true, rewardPhoto: "crown_kings_main_photo", costOfReward: 30)
// ]
@EnvironmentObject private var rewardsViewModel: RewardViewModel
@EnvironmentObject private var loyaltyViewModel: LoyaltyViewModel
@State var rewards: [Reward] = []
func getRewards() async throws -> [Reward]{
let db = Firestore.firestore()
let snapshot = try await db.collection("redeemRewards").getDocuments()
let rewards = snapshot.documents.compactMap{try? $0.data(as: Reward.self)}
return rewards
}
var body: some View {
NavigationStack{
ScrollView {
LazyVGrid (columns: [
GridItem(.flexible()),
GridItem(.flexible()),
], spacing: 16, content:{
ForEach(rewardsViewModel.rewards, id: .self) { reward in
RewardsCardView(rewardPhoto:reward.rewardPhoto, rewardText: reward.rewardText, rewardRedeemed: reward.rewardRedeemed, costOfReward: reward.costOfReward)
.environmentObject(rewardsViewModel)
.environmentObject(loyaltyViewModel)
}
})
}
.onAppear {
Task{
do {
let newRewards = try await getRewards()
rewards.append(contentsOf: newRewards)
} catch {
print("Error Fetching rewards: (error.localizedDescription)")
}
}
}
.navigationTitle("Rewards")
}
}
}
//#Preview {
// RewardsView()
//}
struct Reward: Identifiable, Codable,Hashable {
@DocumentID var id: String?
let rewardText: String
let rewardRedeemed: Bool
let rewardPhoto: String
let costOfReward: CGFloat
let timestamp: Timestamp
let userId: String
let remainingPoints: CGFloat
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Reward, rhs: Reward) -> Bool {
lhs.id == rhs.id
}
}
Am I possibly misunderstanding how a view is constructed at runtime?
Thanks for the help, and consideration.