0

LazyHGrid大家好,我在使用中选择单元格时遇到问题SwiftUI

TimePickerGridView.swift我创建一个水平列表,其中包含用户可以选择的时间。为了管理我使用的单元格选择@State private var selectedItem: Int = 0

一切似乎都有效,但是当我保存用户选择以创建包含所选时间的日期时遇到了一些问题

当用户选择一个单元格时,它会立即通过设置小时和分钟来更新日期。

被修改的日期是@Binding var date: Date,这个日期是指 RiservationViewModel.swift位于RiservationView结构中的

struct ReservationsView: View {
   
    @StateObject var viewModels = ReservationViewModel()
    
    var body: some View {
        VStack {
            TimePickerGridView(date: $viewModels.selectedDate)
        }
    }
}

现在的问题是,当用户选择时间并创建日期时,会LazyHGrid 不断丢失选择,并且必须多次选择同一个单元格才能再次获得正确的选择......

此时会观察到可变日期,因为它可以更改,这要归功于另一个包含用户选择日期的日历的视图。

我怎么解决这个问题?我的错误在哪里?


private extension Date {
    var hour: Int { Calendar.current.component(.hour, from: self) }
    var minute: Int { Calendar.current.component(.minute, from: self) }

    var nextReservationTime: TimePicker {
        let nextHalfHour = self.minute < 30 ? self.hour : (self.hour + 1) % 24
        let nextHalfMinute = self.minute < 30 ? 30 : 0
        return TimePicker(hour: nextHalfHour, minute: nextHalfMinute)
    }
}

struct TimePickerGridView: View {
    @Binding var date: Date
    @State private var selectedItem: Int = 0
    @State private var showNoticeView: Bool = false
   
    private var items: [TimePicker] = TimePicker.items
    
    private func setTimeForDate(_ time: (Int, Int)) {
        guard let newDate = Calendar.current.date(bySettingHour: time.0, minute: time.1, second: 0, of: date) else { return }
        date = newDate
    }
    
    private var startIndex: Int {
        // se trova un orario tra quelli della lista seleziona l'index appropriato
        // altrimenti seleziona sempre l'index 0
        items.firstIndex(of: date.nextReservationTime) ?? 0
    }
    
    init(date: Binding<Date>) {
        // Date = ReservationViewModel.date
        self._date = date
    }
    
    var body: some View {
        VStack(spacing: 20) {
            HStack {
                Spacer()
                TitleView("orario")
                VStack {
                    Divider()
                        .frame(width: screen.width * 0.2)
                }
                Button(action: {}) {
                    Text("RESET")
                        .font(.subheadline.weight(.semibold))
                        .foregroundColor(date.isToday() ? .gray : .bronze)
                        .padding(.vertical, 5)
                        .padding(.horizontal)
                        .background(.thinMaterial)
                        .clipShape(Capsule())
                }
                Spacer()
            }
            ZStack {
                ScrollView(.horizontal, showsIndicators: false) {
                    ScrollViewReader { reader in
                        LazyHGrid(rows: Array(repeating: GridItem(.fixed(60), spacing: 0), count: 2), spacing: 0) {
                            ForEach(items.indices) { item in
                                TimePickerGridCellView(date: $date, selectedItem: $selectedItem, picker: items[item], selection: selectedItem == items.indices[item])
                                    
                                    .frame(width: (UIScreen.main.bounds.width - horizontalDefaultPadding * 2) / 4)
                                    
                                    .onTapGesture {
                                        setTimeForDate((items[item].hour, items[item].minute))
                                        selectedItem = item
                                    }
                                
                                    .onChange(of: date) { _ in
                                        selectedItem = startIndex
                                    }
                                
                                    .onAppear(perform: {
                                        selectedItem = startIndex
                                    })
                            }
                        }
                        .background(Divider())
                    }
                }
                .frame(height: showNoticeView ? 70 : 130)
            }
        }
    }
}
4

0 回答 0