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

如何在Swift iOS事件列表应用中识别并展示跨月/跨年事件

解决跨月/跨年事件的按月展示问题

嘿,这个跨月事件展示的问题我之前做类似日历类App时也碰到过,给你分享个优雅的程序化方案,完全不需要额外加Bool字段,还能自动处理跨年的情况!

核心思路

不用标记事件是否跨月,而是直接基于事件的起止日期区间,判断当前要展示的月份是否落在这个区间内——不管是跨几个月还是跨年,这个逻辑都能通用。

步骤1:封装「年-月」结构体

首先我们创建一个YearMonth结构体,用来统一处理年和月的比较,避免单独处理年、月时的逻辑混乱(尤其是跨年场景):

struct YearMonth: Equatable, Comparable {
    let year: Int
    let month: Int
    
    // 实现比较逻辑:先比年份,再比月份
    static func < (lhs: YearMonth, rhs: YearMonth) -> Bool {
        if lhs.year != rhs.year {
            return lhs.year < rhs.year
        }
        return lhs.month < rhs.month
    }
    
    // 从Date快速生成YearMonth(如果你用Date存储起止日期的话)
    init(from date: Date) {
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month], from: date)
        self.year = components.year!
        self.month = components.month!
    }
    
    // 直接用年、月初始化(如果你是分开存储日/月/年的话)
    init(year: Int, month: Int) {
        self.year = year
        self.month = month
    }
}

步骤2:给事件模型添加判断方法

假设你的事件模型是这样的(不管是用Date还是分开的日/月/年字段都能适配):

struct Event {
    let name: String
    // 如果你用Date存储起止日期
    let startDate: Date
    let endDate: Date
    
    // 判断当前月份是否需要展示该事件
    func shouldShow(in targetYearMonth: YearMonth) -> Bool {
        let eventStartYM = YearMonth(from: startDate)
        let eventEndYM = YearMonth(from: endDate)
        // 只要目标月份在事件的起止月份区间内,就展示
        return targetYearMonth >= eventStartYM && targetYearMonth <= eventEndYM
    }
    
    // ---- 如果你的事件是分开存储日/月/年的,用下面这个版本 ----
    // let startDay: Int, startMonth: Int, startYear: Int
    // let endDay: Int, endMonth: Int, endYear: Int
    // func shouldShow(in targetYear: Int, targetMonth: Int) -> Bool {
    //     let targetYM = YearMonth(year: targetYear, month: targetMonth)
    //     let startYM = YearMonth(year: startYear, month: startMonth)
    //     let endYM = YearMonth(year: endYear, month: endMonth)
    //     return targetYM >= startYM && targetYM <= endYM
    // }
}

步骤3:过滤当前月份的事件

在你的TableView数据源逻辑里,当用户切换到某个月份时,直接过滤事件列表即可:

// 假设用户当前切换到2024年8月
let currentDisplayYM = YearMonth(year: 2024, month: 8)
// 原始事件数组
var allEvents: [Event] = [] // 从Firebase拉取的所有事件
// 过滤出当前月份需要展示的事件
let eventsForCurrentMonth = allEvents.filter { $0.shouldShow(in: currentDisplayYM) }

为什么这个方案更优?

  • 无需修改数据:完全基于事件的原始起止日期计算,不需要额外加标记字段,数据结构更干净
  • 自动处理跨年:YearMonth的比较逻辑先比年份再比月份,像「2024年11月到2025年2月」这种跨年事件,在2024年11、12月和2025年1、2月都会被正确展示
  • 扩展性强:如果以后需要按周/季度展示,只需要修改判断逻辑,不需要改动数据结构

内容的提问来源于stack exchange,提问作者Gibraltar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:29:06