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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:47:28