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 }
第三步:数据加载与实时更新
- 数据加载完成后刷新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() } }
- 可选:实时更新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,提问作者Дмитрий Деникаев
相关产品推荐
相关产品推荐

