首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

iOS CollectionView 多選日曆:跨月份保持選中狀態的資料模型設計

     編輯:程式設計疑難解答

問題核心

CollectionView Cell 會重用(dequeueReusableCellWithReuseIdentifier),滑動換月份時 Cell 被回收重用,若選中狀態只存在 Cell 實例上(如 cell.isSelected),離開畫面後狀態即丟失。

解決方案:資料模型驅動 UI

原則:選中狀態屬於資料模型,不屬於 Cell 視圖。

實作步驟

  1. 定義日期模型:
    struct DayModel {
        let date: Date
        var isSelected: Bool
        // 其他:isCurrentMonth, isToday, eventCount 等
    }
    
  2. 每個月份維護一個陣列:
    var monthData: [Date: [DayModel]] = [:] // key: 月份首日 Date
    
  3. Cell 配置時從模型讀取狀態:
    func collectionView(_ cv: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = cv.dequeueReusableCell(withReuseIdentifier: "DayCell", for: indexPath) as! DayCell
        let day = monthData[currentMonth]![indexPath.item]
        cell.configure(with: day) // 內部設定 day.isSelected ? 高亮 : 正常
        return cell
    }
    
  4. 點擊時更新模型並重載該 Cell:
    
    func collectionView(_ cv: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        var day = monthData[currentMonth]![indexPath.item]
        day.isSelected.toggle()
        monthData[currentMonth]![indexPath.item] = day
        cv.reloadItems(at: [indexPath]) // 或 cv.performBatchUpdates
    }
    
  5. 切換月份時保留/載入對應模型:
    
    func switchToMonth(_ monthStart: Date) {
        currentMonth = monthStart
        if monthData[monthStart] == nil {
            monthData[monthStart] = generateDaysForMonth(monthStart)
        }
        collectionView.reloadData()
    }
    

進階優化

  • 全域選中集合:若需跨月份統計所有選中日期,維護 var selectedDates: Set<Date> = [],Cell 配置時 day.isSelected = selectedDates.contains(day.date)。
  • 持久化:App 退出時將 selectedDates 序列化存入 UserDefaults / CoreData / Realm,啟動時還原。
  • 效能:大量日期時考慮 UICollectionViewCompositionalLayout + Diffable Data Source (iOS 13+),局部更新更高效。

關鍵提醒

  • 切勿在 Cell 類別中儲存業務狀態(如 var isSelected = false)。
  • reloadData() 會重建所有可見 Cell,配合模型正確無誤;若卡頓改用 reloadItems(at:)。
  • 多選邏輯(單選/多選/範圍選)皆在模型層處理,Cell 只負責渲染。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved