You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:48:14