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

Swift中按日期排序事件对象并在Table View展示的问题

问题原因及解决方案

核心问题

你当前的排序逻辑失效,是因为eventDate字段为字符串类型,直接调用compare方法会按字典序排序,而非日期的实际先后顺序。比如字符串"May"在字典序中排在"Aug"之后,但实际日期5月在8月之前,导致排序结果不符合预期。

解决方案

方案1:推荐——将Firebase中的日期存储为Date类型

这是最规范的做法,从根源避免字符串排序的问题:

  1. 存储阶段:将事件日期以Date对象而非字符串存入Firebase;
  2. 读取阶段:在EventObject的初始化方法中,从Firebase文档中取出Date类型值,赋值给eventDate(此时eventDate的类型为Date);
  3. 排序逻辑:直接使用你原有的排序代码即可,Date类型的compare方法会按实际日期顺序比较:
foundEvents.sort(by: { $0.eventDate.compare($1.eventDate) == .orderedAscending })

方案2:临时兼容——将字符串转为Date后再排序

如果暂时无法修改Firebase的存储格式,可以在排序时先把字符串日期转为Date对象再比较:

  1. 定义匹配你存储格式的日期格式化器:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy" // 必须和Firebase中存储的字符串格式完全一致
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // 避免系统语言影响解析结果
  1. 修改排序逻辑:
foundEvents.sort {
    // 把两个字符串日期转为Date对象
    guard let date1 = dateFormatter.date(from: $0.eventDate),
          let date2 = dateFormatter.date(from: $1.eventDate) else {
        return false // 处理解析失败的情况,比如格式不匹配
    }
    // 按日期升序排序
    return date1.compare(date2) == .orderedAscending
}

代码优化建议

你当前使用的DispatchGroup是多余的——因为只有一个getDocuments请求,直接在请求的回调中完成排序和回调即可,简化后的代码如下:

func downloadEventsFromFirebase(withId: String, completion: @escaping (_ events: [EventObject]) -> Void) {
    var foundEvents: [EventObject] = []
    
    FirebaseReference(.Event).whereField(kHOSTID, isEqualTo: withId).getDocuments { (snapshot, error) in
        if let err = error {
            print(err)
            completion(foundEvents)
            return
        }
        guard let snapshot = snapshot else {
            completion(foundEvents)
            return
        }
        
        if !snapshot.isEmpty {
            for event in snapshot.documents {
                let eventObject = event.data() as NSDictionary
                foundEvents.append(EventObject(_dictionary: eventObject))
            }
        } else {
            print("no events to fetch")
        }
        
        // 执行排序(这里用方案2的代码为例)
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd, yyyy"
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        
        foundEvents.sort {
            guard let date1 = dateFormatter.date(from: $0.eventDate),
                  let date2 = dateFormatter.date(from: $1.eventDate) else {
                return false
            }
            return date1 < date2
        }
        
        for event in foundEvents {
            print(event.eventDate)
        }
        completion(foundEvents)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:43:09