Use Location wrapper to decode CLLocation variable

huangapple go评论115阅读模式
英文:

Use Location wrapper to decode CLLocation variable

问题

我目前正在尝试创建一个扩展来使 CLLocation 可编码。为此,我试图复制此线程上的示例:https://stackoverflow.com/questions/64622452/swift-codable-decode-array-of-arrays-of-cllocation

我有以下结构:

struct FriendBase: Identifiable, Encodable {
    var id: UUID = UUID()
    var firstName: String
    var lastKnownLocation: CLLocation? = nil
    
    enum CodingKeys: String, CodingKey {
        case id
        case firstName
        case lastKnownLocation
    }
}

extension FriendBase: Decodable {
    init(from decoder: Decoder) throws {
        let value = try decoder.container(keyedBy: CodingKeys.self)
        
        id = try value.decode(UUID.self, forKey: .id)
        firstName = try value.decode(String.self, forKey: .firstName)
        lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)
    }
}

我基于上面提供的线程实现了一个扩展,如下所示:

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)
    }
}

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)
     }
}

我目前遇到以下错误:Cannot assign value of type 'Location' to type 'CLLocation?',出现在这一行:lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)

感谢您的帮助,我对Swift还很陌生,但我相信我离最终解决方案不远了。

祝好。

英文:

I am currently trying to make an extension to render CLLocation codable. To do so, I am trying to replicate the example on this thread: https://stackoverflow.com/questions/64622452/swift-codable-decode-array-of-arrays-of-cllocation

I have the following structure:

struct FriendBase: Identifiable, Encodable {
    var id: UUID = UUID()
    var firstName: String
    var lastKnownLocation: CLLocation? = nil
    
    enum CodingKeys: String, CodingKey {
        case id
        case firstName
        case lastKnownLocation
    }
}

extension FriendBase: Decodable {
    init(from decoder: Decoder) throws {
        let value = try decoder.container(keyedBy: CodingKeys.self)
        
        id = try value.decode(UUID.self, forKey: .id)
        firstName = try value.decode(String.self, forKey: .firstName)
        lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)
    }
}

I implemented an extension based on the thread provided above which look like this:

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)
    }
}

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)
     }
}

I am currently getting the following error: Cannot assign value of type 'Location' to type 'CLLocation?' on line lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation).

Thanks for your help, I am new with Swift and I believe that I should not be so far for the final solution.

Regards

答案1

得分: 0

在以下代码行:

lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)

属性 lastKnownLocation 声明为 CLLocation? 类型。

而这段代码:

value.decode(Location.self, forKey: .lastKnownLocation)

将返回 Location 类型的值。

因此,出现错误,因为您尝试将 Location 类型的值分配给 CLLocation? 类型的属性。

您已经添加了一个扩展,允许您从 Location 创建 CLLocation。利用这个扩展来进行必要的转换。这意味着您需要将以下行代码更改为:

let location = try value.decode(Location.self, forKey: .lastKnownLocation)
lastKnownLocation = CLLocation(model: location)
英文:

On the line:

lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)

the property lastKnownLocation is declared with a type of CLLocation?.

The code:

value.decode(Location.self, forKey: .lastKnownLocation)

will return a value of type Location.

Hence the error since you are trying to assign a value of type Location to a property of type CLLocation?.

You added an extension that lets you create a CLLocation from a Location. Make use of that to do the needed conversion. This means that you need to change the line:

lastKnownLocation = try value.decode(Location.self, forKey: .lastKnownLocation)

to:

let location = try value.decode(Location.self, forKey: .lastKnownLocation)
lastKnownLocation = CLLocation(model: location)

huangapple
  • 本文由 发表于 2023年8月11日 03:38:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878841.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定