Reputation: 31
I am trying to write an App to predict certain days into the future, and i am having a problem adding decorations to the Calendar View .
When I am trying to either pick a date that is more than 108 days into the future, or I am trying to add a Calendar Decoration to a date that is more than 108 days into the future, my app crashes.
This is the warning from the Log:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to reconfigure item identifier that does not exist in the snapshot: <_UIDatePickerCalendarDay: 0x600000ca8b40; components: 1-2024-2-14; month: <_UIDatePickerCalendarMonth: 0x600000ca8d50; calendar: <_NSSwiftCalendar: 0x60000000d640>; components: 1-2024-2>; assignedMonth: (null)>'
*** First throw call stack:
(
0 CoreFoundation 0x00000001804658a8 __exceptionPreprocess + 172
1 libobjc.A.dylib 0x000000018005c09c objc_exception_throw + 56
2 Foundation 0x0000000180cf3a5c _userInfoForFileAndLine + 0
3 UIKitCore 0x00000001046abe40 -[__UIDiffableDataSourceSnapshot _validateReloadUpdateThrowingIfNeeded:] + 436
4 UIKitCore 0x00000001046abad4 -[__UIDiffableDataSourceSnapshot _commitUpdateAtomic:] + 100
5 UIKitCore 0x00000001046ab0a8 -[__UIDiffableDataSourceSnapshot reconfigureItemsWithIdentifiers:] + 76
6 UIKitCore 0x00000001046db21c -[UICalendarView reloadDecorationsForDateComponents:animated:] + 132
7 DJTimeOff 0x0000000102f18d74 $s9DJTimeOff14DJCalendarViewV12updateUIView_7contextySo010UICalendarD0C_7SwiftUI0F20RepresentableContextVyACGtF + 1208
8 DJTimeOff 0x0000000102f1b430 $s9DJTimeOff14DJCalendarViewV7SwiftUI19UIViewRepresentableAadEP06updateG0_7contexty0G4TypeQz_AD0gH7ContextVyxGtFTW + 12
9 SwiftUI 0x000000010a19a5ac OUTLINED_FUNCTION_9 + 163208
10 SwiftUI 0x000000010a0e611c OUTLINED_FUNCTION_71 + 16892
11 SwiftUI 0x000000010a0e603c OUTLINED_FUNCTION_71 + 16668
12 SwiftUI 0x000000010a0c6b68 OUTLINED_FUNCTION_11 + 63844
13 SwiftUI 0x000000010a0e5ed4 OUTLINED_FUNCTION_71 + 16308
14 SwiftUI 0x000000010a0e5cec OUTLINED_FUNCTION_71 + 15820
15 SwiftUI 0x000000010a0e4f78 OUTLINED_FUNCTION_71 + 12376
16 SwiftUI 0x0000000109c6e1c0 __swift_allocate_boxed_opaque_existential_1Tm + 208
17 AttributeGraph 0x000000019e9fa750 _ZN2AG5Graph11UpdateStack6updateEv + 504
18 AttributeGraph 0x000000019e9faee0 _ZN2AG5Graph16update_attributeENS_4data3ptrINS_4NodeEEEj + 432
19 AttributeGraph 0x000000019ea088d0 _ZN2AG8Subgraph6updateEj + 828
20 SwiftUI 0x0000000109ff7418 OUTLINED_FUNCTION_0 + 10148
21 SwiftUI 0x000000010a0c45a4 OUTLINED_FUNCTION_11 + 54176
22 SwiftUI 0x000000010a0beec0 OUTLINED_FUNCTION_11 + 31932
23 SwiftUI 0x000000010a377578 OUTLINED_FUNCTION_39 + 34700
24 SwiftUI 0x000000010a3775bc OUTLINED_FUNCTION_39 + 34768
25 UIKitCore 0x000000010512ab1c -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1492
26 QuartzCore 0x00000001884d3dd4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 440
27 QuartzCore 0x00000001884deb30 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 124
28 QuartzCore 0x00000001883fa3bc _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 460
29 QuartzCore 0x0000000188429bf0 _ZN2CA11Transaction6commitEv + 652
30 UIKitCore 0x0000000104c30504 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 32
31 CoreFoundation 0x00000001803c6464 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20
32 CoreFoundation 0x00000001803c5bac __CFRunLoopDoBlocks + 352
33 CoreFoundation 0x00000001803c0450 __CFRunLoopRun + 788
34 CoreFoundation 0x00000001803bfd28 CFRunLoopRunSpecific + 572
35 GraphicsServices 0x000000018986ebc0 GSEventRunModal + 160
36 UIKitCore 0x0000000104c17fdc -[UIApplication _run] + 868
37 UIKitCore 0x0000000104c1bc54 UIApplicationMain + 124
38 SwiftUI 0x0000000109af8524 OUTLINED_FUNCTION_70 + 500
39 SwiftUI 0x0000000109af83c4 OUTLINED_FUNCTION_70 + 148
40 SwiftUI 0x000000010980a108 OUTLINED_FUNCTION_2 + 92
41 DJTimeOff 0x0000000102f15db4 $s9DJTimeOff0aB3AppV5$mainyyFZ + 40
42 DJTimeOff 0x0000000102f16340 main + 12
43 dyld 0x00000001030f9558 start_sim + 20
44 ??? 0x00000001032f9f28 0x0 + 4348419880
45 ??? 0xaf6e800000000000 0x0 + 12641181941563916288
)
libc++abi: terminating due to uncaught exception of type NSException
func setDaysOff(startDate:Date, numberOfDays:Int) {
self.changedDayOff = nil
daysOff.removeAll()
let newday = DayOff(firstDay: startDate, dayIcon: .firstDay)
let newday2 = DayOff(firstDay: startDate.diff(numDays: 1), dayIcon: .secondDay)
let newday3 = DayOff(firstDay: startDate.diff(numDays: 2), dayIcon: .thirdDay)
daysOff.append(newday)
daysOff.append(newday2)
daysOff.append(newday3)
for dy in 1...numberOfDays - 1 {
let newDay = DayOff(firstDay: startDate.diff(numDays: 9 * dy),dayIcon: .firstDay)
let newday2 = DayOff(firstDay: startDate.diff(numDays: (9 * dy) + 1), dayIcon: .secondDay)
let newday3 = DayOff(firstDay: startDate.diff(numDays: (9 * dy) + 2), dayIcon: .thirdDay)
daysOff.append(newDay)
daysOff.append(newday2)
daysOff.append(newday3)
}
changedDayOff = newday
}
I am using it like this
func updateUIView(_ uiView: UICalendarView, context: Context) {
if DS.changedDayOff != nil {
for te in 0..<DS.daysOff.count {
uiView.reloadDecorations(forDateComponents: [DS.daysOff[te].dateComponents], animated: true)
}
}
}
Upvotes: 3
Views: 272
Reputation: 55865
I reported this as FB13770006. As a workaround, I believe it's unnecessary to reload decorations before/after that range. The delegate should be invoked to get decorations when the user switches to another month, so I don't think you need to reload decorations for dates that are not currently visible in the calendar. This is my solution:
// UICalendarView crashes when reloadDecorations is called with a date that's too far in the past/future
// But we really only need to reload days in the visible month
// The following verifies it's within 31 days of the visible date components
if let date = dateComponents.date,
let visibleDate = streakCalendarView.visibleDateComponents.date,
let oldestDate = Calendar.current.date(byAdding: .day, value: -31, to: visibleDate),
let newestDate = Calendar.current.date(byAdding: .day, value: 31, to: visibleDate),
date >= oldestDate,
date <= newestDate
{
// Include this dateComponents in the array to reload
}
Upvotes: 0
Reputation: 4435
I too faced this problem, but it seems to be working fine after setting the CalendarView availableDateRange explicitly. Like as given below.
let view = UICalendarView()
view.delegate = context.coordinator
view.calendar = Calendar(identifier: .gregorian)
view.availableDateRange = interval
Where interval is
interval = DateInterval(
start: oneYearAgoDate,
end: Date()
)
Then in inside the function "updateUIView" do the following check, if its with in the available date range or not.
// Check with in the availableDateRange
if uiView.availableDateRange.contains(date) {
dateComponentsArray.append(components)
}
// Then reload decorations
uiView.reloadDecorations(
forDateComponents: dateComponentsArray,
animated: false
)
Hope this helps. :)
Upvotes: 0