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

在Swift中为FIRGeoPoint适配Codable协议并构建Firestore文档模型

实现Firestore文档到Codable结构体的映射(包含GeoPoint类型)

刚好碰到过类似的问题!Firebase的GeoPoint默认并没有实现Codable协议,所以我们需要手动给结构体添加自定义的编码和解码逻辑来处理它。下面是完整的实现代码,我会一步步拆解说明:

import FirebaseFirestore

struct TestStruct: Codable {
    // 和Firestore文档对应的属性
    let name: String
    let aNumber: Double
    let location: GeoPoint
    
    // 定义编码解码的键,要和Firestore文档里的字段名完全一致
    enum CodingKeys: String, CodingKey {
        case name, location, aNumber
    }
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        // 获取顶层解码容器
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // String和Number类型可以直接解码,没有特殊处理
        name = try container.decode(String.self, forKey: .name)
        aNumber = try container.decode(Double.self, forKey: .aNumber)
        
        // 处理GeoPoint:先取出它的嵌套容器,读取经纬度值
        let locationContainer = try container.nestedContainer(keyedBy: GeoPointCodingKeys.self, forKey: .location)
        let latitude = try locationContainer.decode(Double.self, forKey: .latitude)
        let longitude = try locationContainer.decode(Double.self, forKey: .longitude)
        // 用经纬度初始化GeoPoint实例
        location = GeoPoint(latitude: latitude, longitude: longitude)
    }
    
    // 自定义编码逻辑
    func encode(to encoder: Encoder) throws {
        // 获取顶层编码容器
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        // 直接编码String和Number类型
        try container.encode(name, forKey: .name)
        try container.encode(aNumber, forKey: .aNumber)
        
        // 编码GeoPoint:创建嵌套容器,写入经纬度
        var locationContainer = container.nestedContainer(keyedBy: GeoPointCodingKeys.self, forKey: .location)
        try locationContainer.encode(location.latitude, forKey: .latitude)
        try locationContainer.encode(location.longitude, forKey: .longitude)
    }
    
    // 内部枚举,用来对应GeoPoint对象里的经纬度键名
    private enum GeoPointCodingKeys: String, CodingKey {
        case latitude, longitude
    }
}

关键说明:

  • CodingKeys枚举必须和Firestore文档的字段名严格匹配,不然会解码失败。
  • 对于GeoPoint,我们通过嵌套容器来读取/写入它的latitude和longitude属性,因为Firestore存储GeoPoint时,底层是包含这两个字段的对象结构。
  • 自定义init(from:)和encode(to:)方法后,这个结构体就可以直接配合Firestore的API使用了。

使用示例:

当你从Firestore获取到DocumentSnapshot后,可以直接用data(as:)方法解码成TestStruct实例:

func fetchTestDocument() {
    let db = Firestore.firestore()
    db.collection("testCollection").document("testDoc").getDocument { snapshot, error in
        guard let snapshot = snapshot, snapshot.exists else { return }
        do {
            let testItem = try snapshot.data(as: TestStruct.self)
            print("解码结果:\(testItem.name), \(testItem.aNumber), \(testItem.location)")
        } catch {
            print("解码出错:\(error.localizedDescription)")
        }
    }
}

内容的提问来源于stack exchange,提问作者Arda Oğul Üçpınar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:22:01