首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型“”X“”不符合协议“”Encodable“”

类型“”X“”不符合协议“”Encodable“”
EN

Stack Overflow用户
提问于 2018-09-06 13:46:01
回答 2查看 19.8K关注 0票数 9

我希望在这里能对这个错误有一个理解,也许还能对可编码和可解码有更广泛的理解。我的类的一部分如下所示:

代码语言:javascript
复制
  public var eventId: String?
  public var eventName: String?
  public var eventDescription: String?
  public var location: CLLocation?

  /// These properties will be encoded/decoded from JSON
  private enum CodingKeys: String, CodingKey {
    case eventId
    case eventName
    case eventDescription
    case location
  }

  public required convenience init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    let eventId = try container.decode(String?.self, forKey: .eventId)
    let eventName = try container.decode(String?.self, forKey: .eventName)
    let location = try container.decode(CLLocation?.self, forKey: .location)
    self.init(eventId: eventId, eventName: eventName, location:location)
  }

这个类工作得很好,直到我添加了location。当我这样做时,我得到了两个错误:类型'CAEvent‘不符合协议'Encodable',并且在fromDecoder方法中没有上下文类型就无法解析’对成员'location‘的引用。有人能解释一下这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-06 14:05:07

I谷歌和found an article,它们提供了不可编码的CLLocation的实现。

读完那篇文章后,很难为CLLocation实现Decodable。但是作者使用了另一个结构Location来解码CLLocation对象。这很有趣,也很棘手。

适用于可编码

代码语言:javascript
复制
extension CLLocation: Encodable {
    enum CodingKeys: String, CodingKey {
        case latitude
        case longitude
        case altitude
        case horizontalAccuracy
        case verticalAccuracy
        case speed
        case course
        case timestamp
    }
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(coordinate.latitude, forKey: .latitude)
        try container.encode(coordinate.longitude, forKey: .longitude)
        try container.encode(altitude, forKey: .altitude)
        try container.encode(horizontalAccuracy, forKey: .horizontalAccuracy)
        try container.encode(verticalAccuracy, forKey: .verticalAccuracy)
        try container.encode(speed, forKey: .speed)
        try container.encode(course, forKey: .course)
        try container.encode(timestamp, forKey: .timestamp)
    }
}

对于可解码的

代码语言:javascript
复制
struct Location: Codable {
    let latitude: CLLocationDegrees
    let longitude: CLLocationDegrees
    let altitude: CLLocationDistance
    let horizontalAccuracy: CLLocationAccuracy
    let verticalAccuracy: CLLocationAccuracy
    let speed: CLLocationSpeed
    let course: CLLocationDirection
    let timestamp: Date
}
extension CLLocation {
    convenience init(model: Location) {
      self.init(coordinate: CLLocationCoordinate2DMake(model.latitude, model.longitude), altitude: model.altitude, horizontalAccuracy: model.horizontalAccuracy, verticalAccuracy: model.verticalAccuracy, course: model.course, speed: model.speed, timestamp: model.timestamp)
     }
}


/// 
struct Person {
    let name: String
    let location: CLLocation
    enum CodingKeys: String, CodingKey {
        case name
        case location
    }
}
extension Person: Decodable {
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)           
        let name = try values.decode(String.self, forKey: .name)

        // Decode to `Location` struct, and then convert back to `CLLocation`. 
        // It's very tricky
        let locationModel = try values.decode(Location.self, forKey: .location)
        location = CLLocation(model: locationModel)
    }
}
票数 18
EN

Stack Overflow用户

发布于 2018-09-06 16:59:22

根据您希望您的位置包含的内容,您可以添加第二个JSON兼容变量,该变量将在解码器中处理以创建CLLocation。这不是对一个完整的CLLocation进行解码,但可能就是您需要的全部

代码语言:javascript
复制
public var eventId: String?
public var eventName: String?
public var eventDescription: String?
public var location: [Float]? // latitude, longitude
public var cllocation: CLLocation?

/// These properties will be encoded/decoded from JSON
private enum CodingKeys: String, CodingKey {
case eventId
case eventName
case eventDescription
case location
}

public required convenience init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let eventId = try container.decode(String?.self, forKey: .eventId)
let eventName = try container.decode(String?.self, forKey: .eventName)
let location = try container.decode([Float]?.self, forKey: .location)
let cllocation = CLLocation(latitude: CLLocationDegrees(location[0]), CLLocationDegrees(longitude[1]))
self.init(eventId: eventId, eventName: eventName, location:cllocation)

}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52197237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档