Swift中ViewController与CollectionView跨月刷新及数据传递问题求助
Hey there, let's work through this issue step by step. It sounds like you've made good progress so far—getting the swipe gestures working and resolving the initial reloadData issue—but now need to fix passing the available date ranges and ensuring the cells update correctly. Here's how to tackle this:
1. Add a Property to Store Available Date Ranges in Your Calendar View
Right now, your CalendarView (the UIView containing the collection view) doesn't have a way to hold the date ranges that are bookable. Add this property to the class:
class CalendarView: UIView, UICollectionViewDataSource, UICollectionViewDelegate { // Your existing properties var HMonthSDate: Date! var HMonthEDate: Date! // Add this to store available booking ranges var availableDateRanges: [(start: Date, end: Date)] = [] // ... rest of your existing code }
2. Pass Date Ranges When Swiping to a New Month
In your main ViewController's swipe handler, you need to pass both the new month dates and the available booking ranges to the calendar view. Update your swipeMade method:
@objc func swipeMade (_ sender: UISwipeGestureRecognizer) { if sender.direction == .left { NewMonthIndex = HMonthIndex - 1 } else if sender.direction == .right { NewMonthIndex = HMonthIndex + 1 } let returnedValues = BuildNewMonths.GetNewHMonth(for: NewMonthIndex) // Replace `yourAvailableRanges` with your actual variable holding bookable date ranges calenderView.availableDateRanges = yourAvailableRanges calenderView.ProcessMonthDates(NewMonthStartDate: returnedValues.0, NewMonthEndDate: returnedValues.1) // You can remove the direct `calenderView.myCollectionView.reloadData()` call here— // `ProcessMonthDates` already triggers it, and duplicate calls aren't needed }
3. Update cellForItemAt to Check Date Availability
Your current cellForItemAt only sets the background color—you need to calculate the date for each cell, verify if it's in the current month, and then check if it falls within an available range. Here's an improved version:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! dateCVCell cell.backgroundColor = .clear // Calculate the date corresponding to this cell let firstDayOffset = getFirstDayOfMonthOffset() // Helper method below guard let cellDate = Calendar.current.date(byAdding: .day, value: indexPath.row - firstDayOffset, to: HMonthSDate) else { // Invalid date—disable and gray out the cell cell.isUserInteractionEnabled = false cell.textLabel?.textColor = .lightGray return cell } // Check if the date belongs to the current month let isInCurrentMonth = Calendar.current.isDate(cellDate, equalTo: HMonthSDate, toGranularity: .month) if !isInCurrentMonth { cell.isUserInteractionEnabled = false cell.textLabel?.textColor = .lightGray cell.textLabel?.text = "\(Calendar.current.component(.day, from: cellDate))" return cell } // Check if the date is in any available booking range var isBookable = false for range in availableDateRanges { if cellDate >= range.start && cellDate <= range.end { isBookable = true break } } // Update cell state based on availability cell.isUserInteractionEnabled = isBookable cell.textLabel?.textColor = isBookable ? .black : .lightGray cell.textLabel?.text = "\(Calendar.current.component(.day, from: cellDate))" return cell } // Helper to calculate how many empty cells we need before the first day of the month private func getFirstDayOfMonthOffset() -> Int { // Adjust this based on your calendar's start day (Calendar API uses 1=Sunday, 2=Monday...7=Saturday) let weekday = Calendar.current.component(.weekday, from: HMonthSDate) // For Sunday-start calendars, subtract 1 to get a 0-indexed offset return weekday - 1 }
4. Ensure reloadData Runs on the Main Thread
All UI updates must happen on the main thread—update your ProcessMonthDates method to guarantee this:
func ProcessMonthDates(NewMonthStartDate: Date, NewMonthEndDate: Date) { HMonthSDate = NewMonthStartDate HMonthEDate = NewMonthEndDate DispatchQueue.main.async { self.myCollectionView.reloadData() } }
5. Verify Your Calendar View Reference
Double-check that the calenderView variable in your main ViewController points to the actual instance of CalendarView added to your view hierarchy. If you accidentally create a new instance instead of referencing the existing one, your data won't update on the screen.
With these changes, when you swipe to a new month, the calendar view will receive the correct available date ranges, reload its cells, and update each cell's state based on whether the date is bookable.
内容的提问来源于stack exchange,提问作者hbm

