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

Swift 4中能否用标准方式实现Firebase GeoPoint的编解码?

没错,Firebase的GeoPoint确实没有默认实现Codable协议,所以直接在自定义的Codable类里使用它会触发你遇到的解码错误。不过我们有两种简单的解决方案,帮你搞定这个问题:

方案一:在自定义类中手动实现编码解码逻辑

首先注意下,Data是Swift系统自带的类型,建议把你的类名改成DataModel之类的,避免命名冲突。然后我们可以手动处理GeoPoint的解码和编码:

final class DataModel: Codable {
    var location: GeoPoint = GeoPoint(latitude: 0, longitude: 0)
    
    // 对应JSON里的"geoloc"字段
    private enum CodingKeys: String, CodingKey {
        case geoloc
    }
    
    // 解析GeoPoint内部的纬度、经度字段
    private enum GeoPointKeys: String, CodingKey {
        case latitude, longitude
    }
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 取出"geoloc"对应的嵌套容器
        let geoContainer = try container.nestedContainer(keyedBy: GeoPointKeys.self, forKey: .geoloc)
        
        // 解码纬度和经度
        let latitude = try geoContainer.decode(Double.self, forKey: .latitude)
        let longitude = try geoContainer.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)
        // 创建"geoloc"对应的嵌套容器
        var geoContainer = container.nestedContainer(keyedBy: GeoPointKeys.self, forKey: .geoloc)
        
        // 编码纬度和经度
        try geoContainer.encode(location.latitude, forKey: .latitude)
        try geoContainer.encode(location.longitude, forKey: .longitude)
    }
}
方案二:给GeoPoint扩展Codable协议

如果你的项目里很多地方都要用到GeoPoint的编解码,更高效的方式是直接给GeoPoint扩展Codable,这样所有用到它的Codable类都能自动处理:

extension GeoPoint: Codable {
    private enum CodingKeys: String, CodingKey {
        case latitude, longitude
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let latitude = try container.decode(Double.self, forKey: .latitude)
        let longitude = try container.decode(Double.self, forKey: .longitude)
        self.init(latitude: latitude, longitude: longitude)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(latitude, forKey: .latitude)
        try container.encode(longitude, forKey: .longitude)
    }
}

扩展之后,你的自定义类就可以简化成这样,不用再手动写编解码逻辑:

final class DataModel: Codable {
    // 直接把JSON里的"geoloc"映射到location属性
    var location: GeoPoint = GeoPoint(latitude: 0, longitude: 0)
    
    private enum CodingKeys: String, CodingKey {
        case location = "geoloc"
    }
}

两种方案都能解决你遇到的问题,根据你的项目需求选择就好~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:27:47