Open benrudhart opened 2 weeks ago
Hi @benrudhart, could you share the code that is producing the crash?
I wasn't able to reproduce on my end. Here's what I tried (2.1.0, iOS 17.5):
struct ContentView: View {
@State private var dateRange = DateInterval(start: .distantPast, end: .distantFuture)
var body: some View {
VStack {
CalendarView(availableDateRange: dateRange)
Button("Last Month Only") {
let c = Calendar.current
let lastMonth = c.date(byAdding: .month, value: -1, to: Date())!
let lastMonthRange = c.dateInterval(of: .month, for: lastMonth)!
dateRange = .init(start: lastMonthRange.start, end: lastMonthRange.end - 1)
}
}
}
}
Hi @AllanJuenemann, sure, and sorry for not adding the example in the beginning.
I took your example and extended it a bit, so the crash is reproducible. One way to force the crash is to also setup the visibleDateComponents
.
I feel like this crash should be prevented from CalendarView
struct ContentView: View {
@Environment(\.calendar) private var calendar
@State private var dateRange = DateInterval(start: .distantPast, end: .now)
@State private var visibleDateComponents = Calendar.current.dateComponents(in: .current, from: .now)
var body: some View {
VStack {
CalendarView(
availableDateRange: dateRange,
visibleDateComponents: $visibleDateComponents
)
Button("Last Month Only") {
decrementMonth()
}
}
}
private func decrementMonth() {
let lastMonth = calendar.date(byAdding: .month, value: -1, to: dateRange.end)!
let lastMonthRange = calendar.dateInterval(of: .month, for: lastMonth)!
dateRange = .init(start: lastMonthRange.start, end: lastMonthRange.end - 1)
fixVisibleDateComponentsIfNeeded()
}
private func fixVisibleDateComponentsIfNeeded() {
let end = calendar.dateComponents(in: .current, from: dateRange.end)
if let endMonth = end.month,
visibleDateComponents.month! > endMonth {
// important: not updating `visibleDateComponents` will cause a crash.
//visibleDateComponents = end
}
// -> must do the same for the start month as well
}
}
Thank you, @benrudhart. Great find.
The crash is due to an exception thrown by UICalendarView.setVisibleDateComponents(_:animated:). In fact, the documentation states that what's passed to setVisibleDateComponents(_:animated:)
has to be within range of availableDateRange
.
But I agree with you. This should be handled gracefully by CalendarView
. I'll fix it for the next release.
Great - thank you. Looking forward.
Updating
availableDateRange
with a lower end than the currently visible month leads to a crash. The a crash is somewhere in deep in UICalendar. Is this a known issue?