I need to fetch some data before passing it to a View. I created a ViewModel BoughtItemViewModel for the my BoughtItemView.
For simplicity I only provide one case, my enum has some more cases I switch through depending on what item is bought. This is the BoughtItemView:
enum SomeType {
case song(Song)
}
struct BoughtItemCard: View {
@State var type: SomeType
@StateObject var vm = BoughtItemViewModel()
var body: some View {
switch type {
case .song(let song):
WebImage(url: URL(string: song.image))
.resizable()
.frame(width: 150, height: 150)
.overlay(BoughtItemOverlay(type: type)
.environmentObject(vm)
.onAppear() {
vm.fetchUnlockDate(path: "songs", docId: song.id ?? "")
}
}
}
This is the BoughtItemViewModel:
class BoughtItemViewModel: ObservableObject {
@Published var unlockDate = Date()
func fetchUnlockDate(path: String, docId: String) {
let uid = FirebaseManager.shared.auth.currentUser?.uid ?? ""
FirebaseManager.shared.firestore.collection(path)
.document(docId).collection("unlocked").document(uid).getDocument { docSnapshot, error in
if let error = error {
print(error)
return
}
let data = docSnapshot?.data()
self.unlockDate = (data?["unlockDate"] as? Date ?? Date())
}
}
}
Now I want the unlockDatein my BoughtItemOverlay View to show the fetched date.
Again for simplicity I provide one case, this is the BoughtItemOverlay:
struct BoughtItemOverlay: View {
@State var showModal: Bool = false
@State var type: SomeType
@State var unlockDate = Date()
@EnvironmentObject var vm: BoughtItemViewModel
var body: some View {
switch type {
case .song(let song):
VStack {
Spacer().onAppear() {
unlockDate = vm.unlockDate
}
Text("Purchased \(unlockDate.formatted(.dateTime.day().month(.defaultDigits).year()))")
}
}
}
}
Instead of displaying the unlockDate it always displays the date of today. I'm not sure why that is since the BoughtItemOverlayshould refresh after the State changes in the onAppear() setting the value to the BoughtItemViewModel value. Atleast that I think it should work that way, but correct me if I'm wrong.