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

CollectionView展示时间价格:需关闭并灰化已过时段

实现CollectionView中已过时段的禁用与灰色样式

看起来你已经完成了数据加载的核心逻辑,接下来只需要添加时间判断和Cell样式控制就能实现需求。我会一步步帮你梳理实现方案:


第一步:完善时间比较的辅助逻辑

首先你需要一个方法来判断某个时段是否已经过期。假设你的PriceTime模型里存储了时段的开始时间(比如time: Date或者hour: Int),我们分两种情况处理:

情况1:PriceTime存储的是Date类型的时段开始时间

先定义一个日期格式化器(如果后端返回的是时间字符串,也需要它来转成Date):

private let timeFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "HH:mm"
    formatter.locale = Locale(identifier: "en_US_POSIX")
    return formatter
}()

然后写判断过期的方法,按照你的例子(14:51时关闭14:00之前的时段),逻辑是时段结束时间(开始时间+1小时)早于当前时间则过期:

private func isTimeSlotExpired(_ priceTime: PriceTime) -> Bool {
    let currentDate = Date()
    // 假设每个时段时长为1小时,计算时段结束时间
    guard let endTime = Calendar.current.date(byAdding: .hour, value: 1, to: priceTime.time) else {
        return false
    }
    // 结束时间早于当前时间,说明时段已过
    return endTime < currentDate
}

情况2:PriceTime存储的是Int类型的小时数(比如13代表13:00)

判断逻辑会更简单:

private func isTimeSlotExpired(hour: Int) -> Bool {
    let currentHour = Calendar.current.component(.hour, from: Date())
    // 时段结束小时(当前小时+1)小于等于当前时间的小时,说明已过
    return (hour + 1) <= currentHour
}

第二步:在CollectionView Cell中应用状态判断

在cellForItemAt方法里,根据过期状态设置Cell的样式和交互性:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TimePriceCell", for: indexPath) as! TimePriceCell
    let currentItem = priceTime[indexPath.item]
    
    // 1. 设置基础内容
    cell.timeLabel.text = timeFormatter.string(from: currentItem.time) // 或者直接用currentItem.hour转成字符串
    cell.priceLabel.text = String(format: "¥%.2f", currentItem.price)
    
    // 2. 判断是否过期并设置样式
    let isExpired = isTimeSlotExpired(currentItem) // 对应情况1;如果是情况2则传currentItem.hour
    if isExpired {
        // 已过期:灰色样式+禁止点击
        cell.backgroundColor = .systemGray5
        cell.timeLabel.textColor = .systemGray
        cell.priceLabel.textColor = .systemGray
        cell.isUserInteractionEnabled = false
    } else {
        // 未过期:正常样式+允许点击
        cell.backgroundColor = .white
        cell.timeLabel.textColor = .label
        cell.priceLabel.textColor = .label
        cell.isUserInteractionEnabled = true
    }
    
    return cell
}

第三步:数据加载与实时更新

  1. 数据加载完成后刷新CollectionView:
    在你的getDataFromBackend()方法末尾添加刷新逻辑:
func getDataFromBackend() {
    Firestore.firestore().collection("priceTimes").getDocuments { [weak self] snapshot, error in
        guard let self = self, let snapshot = snapshot else {
            // 处理错误
            return
        }
        // 解析数据到priceTime数组
        self.priceTime = snapshot.documents.compactMap { doc in
            guard let timeStr = doc["time"] as? String, 
                  let time = self.timeFormatter.date(from: timeStr),
                  let price = doc["price"] as? Double else {
                return nil
            }
            return PriceTime(time: time, price: price)
        }
        // 刷新CollectionView
        self.collectionView.reloadData()
    }
}
  1. 可选:实时更新UI
    如果需要过整点后自动刷新(比如15:00时自动禁用14:00的时段),可以添加定时器:
private var updateTimer: Timer?

override func viewDidLoad() {
    super.viewDidLoad()
    // 初始化CollectionView、加载数据...
    getDataFromBackend()
    
    // 每分钟检查一次时间并刷新
    updateTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { [weak self] _ in
        self?.collectionView.reloadData()
    }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // 页面消失时销毁定时器,避免内存泄漏
    updateTimer?.invalidate()
    updateTimer = nil
}

内容的提问来源于stack exchange,提问作者Дмитрий Деникаев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:06:12