I am trying to use the MultiDatePicker in SwiftUI, but can't get it working properly with a custom binding. The problem I'm facing is that it's acting as a single date picker, not a mutli date picker (selecting a 2nd date, deselects the 1st selected date).
This is part of a KMM project, and I have a viewModel that's written in Kotlin and lives in shared code. There is a Swift wrapper around this that holds/exposes a single state object containing all state (as an observableObject), and passes events back to the shared code.
Throughout the project we manually create bindings like this:
Binding(
get: {state.property},
set: {onEvent(someEvent(value: $0)}
)
This usually works fine, but I'm having problems with the MultiDatePicker.
Here's my datepicker code:
MultiDatePicker(
SharedRes.strings().please_select_dates.asString(),
selection: Binding(
get: {
print(newBenefit.blackoutDates)
return Set( newBenefit.blackoutDates.compactMap{
cal.dateComponents([.calendar, .era, .year, .month, .day], from: $0.toSwiftDate()!)}
)
},
set: { value in
blackoutDatesChanged(value.compactMap{cal.date(from: $0)})
}
)
)
Text(newBenefit.blackoutDates.compactMap{$0.toSwiftDate()}.toMultiDateString())
newBenefit.blackoutDates is a list of KotlinXLocalDates and blackoutDatesChanged is defined as let blackoutDatesChanged: ([Date]) -> Void
I've added a print(newBenefit.blackoutDates) inside the get, to try and see what's happening.
When I select the first date, the get block is run twice - I get an empty list printed, followed by a list containing the selected date. The text below the picker correctly shows the date I've selected. I.e. newBenefit.blackoutDates is correctly being updated by my set.
When I select the second date, I get the same result. I get an empty list printed, followed by a list containing a single date (the 2nd selected date).
It seems like - on selecting a date, the datepicker is calling the get to get a list of previous dates, then adding the newly selected date into that, then calling the set with that new list (which will update my state, triggering a new call to get). Setting breakpoints appears to confirm this - get gets hit, then set, then get again!
However, every time on that first 'get' call (when clicking a date), my list of current dates is showing as empty. Almost as though the get isn't reading the current list, but reading the state as it was when the datepicker was first initialized. So, the previously selected date is ignored, and when calling the set it's only passing in that 2nd selected date.
Any help figuring this out is greatly appreciated.