Reputation: 51
UPDATED
I'm pulling events from IOS calendar with EventKit. Working great.
Here's the class function that retrieves the events.
@ObservedObject var selectDate = datepicker() // does NOT update as expected.
func loadEvents(completion: @escaping (([EKEvent]?) -> Void)) {
requestAccess(onGranted: {
let startOfDay = Calendar.current.startOfDay(for: self.selectDate.selectedDate)
let endOfDay = Calendar.current.startOfDay(for: self.selectDate.selectedDate.advanced(by: TimeInterval.day))
let predicate = self.eventStore.predicateForEvents(withStart: startOfDay, end: endOfDay, calendars: Array(self.selectedCalendars ?? []))
let events = self.eventStore.events(matching: predicate)
completion(events)
print("loadEvents triggered for \(self.selectDate.selectedDate)") // This ALWAYS returns the current date
}) {
completion(nil)
}
}
I want to update the results based on a chosen date. so I have a date picker assigned to a @ObservedObject var selectDate in my main view
@ObservedObject var selectDate = datepicker()
DatePicker(
selection: $selectDate.selectedDate,
in: dateClosedRange,
displayedComponents: [.date, .hourAndMinute], label: { Text("Is hidden label") })
}
And this class is acting as the middle man. The didSet
method is triggering the function to run, confirmed by the print statement in the loadEvents
func above.
class datepicker: ObservableObject {
@Published var selectedDate: Date = Date() {
didSet {
print("class datepicker date changed to \(selectedDate)") // This returns the changed dates correctly
EventsRepository.shared.loadAndUpdateEvents()
}
}
}
I've tried passing the new date like this too.
let startOfDay = Calendar.current.startOfDay(for: datepicker.init().selectedDate)
With the same persistent "current date" only result.
How can I pass the new selectedDate to the function whenever the selectDate.selectedDate from the datePicker is changed?
At the moment it doesn't update at all. Always returns events for the current day only.
The print statements contained in the above code in Debug return.
"class datepicker date changed to 2020-08-13 19:23:28 +0000" // YEP That's right. I used datePicker to select this date.
"loadEvents triggered for 2020-08-10 19:23:28 +0000" // NOT updated, ALWAYS shows current date/time as first run.
So it looks like @Published property is a constant and can not be changed once set. Is there an alternative?
Upvotes: 1
Views: 858
Reputation: 54516
How can I re-trigger the func loadEvents whenever the selectDate.selectedDate from the datePicker is changed?
You can try using didSet
:
class datepicker: ObservableObject{
@Published var selectedDate: Date = Date() {
didSet {
// loadEvents()
}
}
}
Tested with Xcode 11.6, iOS 13.6.
EDIT
It looks like you're using two instances of datepicker
object. Make sure you're using the same instance in all relevant places.
This object should only be created once:
@ObservedObject var selectDate = datepicker()
Then passed to other places in init
.
Upvotes: 2
Reputation: 4503
One way to do this, is to actually subscribe to your own publisher when you create your model object.
class DateManager: ObservableObject {
@Published var selectedDate: Date = .init()
private var bag: Set<AnyCancellable> = []
init() {
$selectedDate // $ prefix gets the projected value, a `Publisher` from `Published<>`
.receive(on: DispatchQueue.main)
.sink { [weak self] selectedDate in
self?.loadEvents(date: selectedDate)
}
.store(in: &bag)
}
}
This will subscribe to that publisher and trigger your API call when it changes. you can get fancy and add debounce
or small delays if the user is rapidly changing dates, etc. you now have the full power of combine to control this data flow.
Upvotes: 1