如何将Firebase数据库数据按距离远近排序后存入自定义对象?
解决步骤:解析Firebase数据并按距离排序
我来帮你一步步搞定这个问题,分三个核心环节:把Firebase数据转成DonatorItem模型、计算每个条目到用户的距离、最后按距离排序。
1. 完善DonatorItem模型
首先得让你的DonatorItem能从Firebase的字典数据里初始化,同时预留存储距离的属性:
struct DonatorItem { let id: String let name: String let description: String let latitude: Double let longitude: Double let pickUpDate: Date let selectedType: String var distanceToUser: Double? // 用来存计算后的距离值 } // 扩展初始化方法,从Firebase字典生成模型 extension DonatorItem { init?(id: String, firebaseDict: [String: Any]) { guard let name = firebaseDict["name"] as? String, let description = firebaseDict["description"] as? String, let latStr = firebaseDict["latitude"] as? String, let latitude = Double(latStr), let lonStr = firebaseDict["longitude"] as? String, let longitude = Double(lonStr), let dateStr = firebaseDict["pickUpDate"] as? String, let pickUpDate = ISO8601DateFormatter().date(from: dateStr), let selectedType = firebaseDict["selectedType"] as? String else { return nil // 数据解析失败时返回nil } self.id = id self.name = name self.description = description self.latitude = latitude self.longitude = longitude self.pickUpDate = pickUpDate self.selectedType = selectedType } }
注意:Firebase里存的经纬度是字符串类型,需要转成Double;日期用ISO8601DateFormatter解析,刚好匹配你数据里的格式。
2. 修改数据获取方法,完成解析+距离计算+排序
更新你的fetchDonatorsItemsFromFirebase方法,把字典转成模型、计算距离、再排序:
var donatorsItems = [DonatorItem]() func fetchDonatorsItemsFromFirebase() { donatorsItems.removeAll() rootRef.child(FirebaseRoot.donatorsItems.rawValue).observe(.value) { [weak self] snapshot in guard let self = self else { return } // 用Swift原生字典替代NSDictionary,更安全 guard let itemDict = snapshot.value as? [String: [String: Any]] else { self.donatorsItems = [] // 这里可以加刷新UI的代码,比如tableView.reloadData() return } var tempItems = [DonatorItem]() for (itemId, nestedDict) in itemDict { // 把Firebase数据转成DonatorItem if var item = DonatorItem(id: itemId, firebaseDict: nestedDict) { // 调用你的方法计算距离 let distance = self.getDistanceFromUserToMeetingPoint(item.latitude, item.longitude, vc: self) item.distanceToUser = distance tempItems.append(item) } } // 按距离从近到远排序,距离计算失败的条目放到最后 self.donatorsItems = tempItems.sorted { guard let distA = $0.distanceToUser, let distB = $1.distanceToUser else { return false } return distA < distB } // 数据处理完成后刷新UI // self.tableView.reloadData() } }
这里做了几个关键优化:
- 用Swift原生的
[String: [String: Any]]替代NSDictionary,避免类型转换的不安全问题 - 遍历的时候直接拿到Firebase生成的条目ID(就是那个autoId)和对应的数据字典
- 计算每个条目的距离并存储到模型中
- 用
sorted方法对数组排序,确保结果是从近到远排列
3. 额外注意点
- 确保
getDistanceFromUserToMeetingPoint方法已经正确获取到用户的当前位置,否则距离计算会出错,建议在调用fetch方法前先完成用户位置授权和获取 - 如果Firebase的日期格式和默认的
ISO8601DateFormatter不匹配,可以自定义格式,比如:let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] // 适配带毫秒的日期
内容的提问来源于stack exchange,提问作者Roland Lariotte
相关产品推荐
相关产品推荐

