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

Swift Codable枚举编码成功但解码失败问题求助

问题描述

我通过嵌套Codable类型定义了GeoJSONFeatureGeometryCoordinates枚举,用于解码GeoJSON文件中的点、多边形与多多边形。解码GeoJSON文件时一切正常,但将该数据编码为二进制数据存储到Core Data后,再次解码却失败,抛出typeMismatch错误。

枚举代码

enum GeoJSONFeatureGeometryCoordinates: Codable {
    
    case point([Double])
    case polygon([[[Double]]])
    case multipolygon([[[[Double]]]])

    
    init(from decoder: Decoder) throws {
        
        let container = try decoder.singleValueContainer()
        
        do {
            
            let polygonVal = try container.decode([[[Double]]].self)
            self = .polygon(polygonVal)
        } catch DecodingError.typeMismatch {
            do {
                
                let multipolygonVal = try container.decode([[[[Double]]]].self)
                self = .multipolygon(multipolygonVal)
            } catch DecodingError.typeMismatch {
                
                let pointVal = try container.decode([Double].self)
                self = .point(pointVal)
            }
        }
    }
}

测试代码

do {
    let encoder = JSONEncoder()
    let encodedCoordinates = try encoder.encode(centroid.geometry.coordinates)
    
    let decoder = JSONDecoder()
    let decodedCoordinates = try decoder.decode(GeoJSONFeatureGeometryCoordinates.self, from: encodedCoordinates)
} catch {
    fatalError("\n\n Error archiving feature.geometry.coordinates as Data")
}
解决方案

问题出在你只手动实现了解码逻辑init(from:),但没有实现对应的编码逻辑encode(to:)。Codable自动合成的编码逻辑无法正确处理这种嵌套数组类型的枚举,导致编码后的数据格式和解码时预期的单一值容器不匹配,最终触发typeMismatch错误。

需要手动添加encode(to:)方法,根据枚举的case类型将对应的数据编码到单一值容器中:

enum GeoJSONFeatureGeometryCoordinates: Codable {
    
    case point([Double])
    case polygon([[[Double]]])
    case multipolygon([[[[Double]]]])

    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        do {
            let polygonVal = try container.decode([[[Double]]].self)
            self = .polygon(polygonVal)
        } catch DecodingError.typeMismatch {
            do {
                let multipolygonVal = try container.decode([[[[Double]]]].self)
                self = .multipolygon(multipolygonVal)
            } catch DecodingError.typeMismatch {
                let pointVal = try container.decode([Double].self)
                self = .point(pointVal)
            }
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .point(let value):
            try container.encode(value)
        case .polygon(let value):
            try container.encode(value)
        case .multipolygon(let value):
            try container.encode(value)
        }
    }
}

添加这个方法后,编码时会将每个枚举case对应的数据以单一数组的形式写入,和解码时的读取逻辑完全匹配,二次解码就能正常完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:45:34