HorizonCalendar icon indicating copy to clipboard operation
HorizonCalendar copied to clipboard

When I want to get selected Days with using binding in swiftui, it triggers DayViewItem again and again.

Open savrano opened this issue 1 year ago • 0 comments

I have a view model as you can see the below and I want to get selected days in my viewModel

final class DatePickerViewModel: ObservableObject {
    @Published var selectedDates = ""
}

This one created for the test. I just want to get with text when user select days on the date picker.

struct SwiftUITestView: View {
    @StateObject var viewModel = DatePickerViewModel()
    let monthsLayout: MonthsLayout = .vertical(options: VerticalMonthsLayoutOptions())
    var body: some View {
        VStack{
            Text(viewModel.selectedDates)
            SwiftUIScreenDemo(calendar: Calendar.current, monthsLayout: monthsLayout, selectedDates: $viewModel.selectedDates)
        }
    }
}

And I need to pass variable using @Binding property wrapper Because I want to get changes from view model. I passed data like the below in the SwiftUIScreenDemo

@Binding var selectedDates: String
init(..., selectedDates: Binding<String>) {
    self._selectedDates = selectedDates
}

I have a func in SwiftUIScreenDemo that inside of .dayItemProvider function. And this function for just get selected date.

private func manageMultipleDaySelection(isSelected: Bool, selectedDayRange: DayRange?) {
        if isSelected && selectedDayRange != nil {
            let firstRange = selectedDayRange?.lowerBound.description ?? ""
            let lastRange = selectedDayRange?.upperBound.description ?? ""
            
            selectedDates = firstRange == lastRange ? firstRange : "\(firstRange) - \(lastRange)"
        }
    }

I used it .dayItemProvider.

.dayItemProvider { day in
            let isSelected: Bool
            if let selectedDayRange {
                isSelected = day == selectedDayRange.lowerBound || day == selectedDayRange.upperBound
            } else {
                isSelected = false
            }
            let dayView = SwiftUIDayView(dayNumber: day.day, isSelected: isSelected)
            self.manageMultipleDaySelection(isSelected: isSelected, selectedDayRange: selectedDayRange)
            return dayView
                .calendarItemModel
            
        }

So When I run app and select a day on the datepicker, It keeps going generate day at dayItemProvider. And memory usage continue increase and CPU usage %100. Ui did deadlock. When we set selectedDates in the DispatchQueue.main.async this time doesn't deadlock but It continue generate day on the background. But if selectedDates is marked with @State property wrapper in SwiftUIScreenDemo, there is no problem. It works right. Why is it acting like this? If I need to bind this parameter (which I need), what should I do?

savrano avatar Apr 06 '23 12:04 savrano