Home > front end >  How to read property from a struct when being in @ObservableObject
How to read property from a struct when being in @ObservableObject

Time:04-18

I don't know how to read a property that is in a struct from a class that is an Observable Object.

Context:

I'm trying to build an app which consists of 2 views:

  • a custom calendar;
  • a popup with a header 'Daily Joke', date formatted as 'MM-dd-yyyy' and a joke text that is fetched from Firebase using id. When the user clicks on a date in the calendar, the popup appears and shows the joke for a selected date.

The problem is that the 'currentDate' property (holds the value of the selected date) that I reference in the ObservableObject of the 'getJoke' class won't update when the user selects a different date. It always fetches the joke on today's date and not on the one the user has selected.

Here is the code of:

  • the custom calendar (selected date is held in the property 'currentDate')
import SwiftUI
import grpc

struct CustomDatePicker: View {
    
    @State var currentDate: Date
    @State var dailyJokePopUp = false

  //some code here
                        // When the user selects the date, currentDate property changes to the selected date
                        .onTapGesture {
                            currentDate = value.date
                        }

  //  Getting selected day for displaying in dailyJokePopUp
    func getCurrentDay()->String{
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy"
        let date = dateFormatter.string(from: currentDate)
        return date
    }

    
  • the class which is an @ObservableObject (I use it to add a listener to the Firebase to fetch the joke text by its id. Here I need to read 'currentDate' which is originally declared and changed in CustomDatePicker. I need to do it to check if 'currentDate' matches the id in Firebase (that way the joke text is fetched from Firebase on the selected date)).
    class getJoke : ObservableObject {
        
        @Published var data = [JokeX]()
        @Published var noData = false
        @Published var currentDate = Date()
        
    //some code here including adding SnapShotListener
                
                let callCDP = CustomDatePicker(currentDate: currentDate).getCurrentDay()
                if id == callCDP {
                    self.data.append(joke_text_imported)}

                }
            }

    }
    }
    
  • the popup (I call the result of the @ObservableObject to get the display the text fetched from Firebase)
import SwiftUI

struct dailyJokePopUp: View {
    
    @Binding var show: Bool
    @ObservedObject var Jokes = getJoke()    

    var currentDate: Date = Date()
    
 //some code here

  ForEach(self.Jokes.data){i in
  Text(i.joke_text)
  }

 //some code here
}

I can suspect something is wrong with how I declare properties. I've tried various wrappers (@Binding, @StateObject), but I got confused and it didn't work. Hope someone can be kind enough to help me solve the problem.

CodePudding user response:

ViewModel

class getJoke: ObservableObject {
  @Published var currentDate = Date()
}

View that can change passing data

struct CustomDatePicker: View {

  @Binding var currentDate: Date

  var body: some View{
      VStack {
          DatePicker(selection: $currentDate, displayedComponents: .date){
                Text("Select your date")
          }
          .datePickerStyle(.compact)
      }
  }
}

And put everything together

    struct ContentView: View {
    
    @StateObject var vm = getJoke()
    
    var body: some View {
        VStack(spacing: 40) {
            CustomDatePicker(currentDate: $vm.currentDate)
            Button {
                print(vm.currentDate)
            } label: {
                Text("Show selected date")
            }

        }
    }
}
  • Related