Swift中按日期排序事件对象并在Table View展示的问题
问题原因及解决方案
核心问题
你当前的排序逻辑失效,是因为eventDate字段为字符串类型,直接调用compare方法会按字典序排序,而非日期的实际先后顺序。比如字符串"May"在字典序中排在"Aug"之后,但实际日期5月在8月之前,导致排序结果不符合预期。
解决方案
方案1:推荐——将Firebase中的日期存储为Date类型
这是最规范的做法,从根源避免字符串排序的问题:
- 存储阶段:将事件日期以
Date对象而非字符串存入Firebase; - 读取阶段:在
EventObject的初始化方法中,从Firebase文档中取出Date类型值,赋值给eventDate(此时eventDate的类型为Date); - 排序逻辑:直接使用你原有的排序代码即可,
Date类型的compare方法会按实际日期顺序比较:
foundEvents.sort(by: { $0.eventDate.compare($1.eventDate) == .orderedAscending })
方案2:临时兼容——将字符串转为Date后再排序
如果暂时无法修改Firebase的存储格式,可以在排序时先把字符串日期转为Date对象再比较:
- 定义匹配你存储格式的日期格式化器:
let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MMM dd, yyyy" // 必须和Firebase中存储的字符串格式完全一致 dateFormatter.locale = Locale(identifier: "en_US_POSIX") // 避免系统语言影响解析结果
- 修改排序逻辑:
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
相关产品推荐
相关产品推荐

