#swift #firebase #google-cloud-firestore #codable
#swift #firebase #google-облако-firestore #кодируемый
Вопрос:
У меня возникли трудности с декодированием и кодированием одного из моих классов в Swift. Я попытался следовать документации по кодированию и декодированию пользовательских типов, но безуспешно.
Мой макет класса выглядит следующим образом:
public struct MapLocation: Identifiable, Codable {
@DocumentID public var id: String?
let originLocation: [MapLandmark]
let destinationLocation: [MapLandmark]
enum CodingKeys: String, CodingKey {
case originLocation
case destinationLocation
}
}
import Foundation
import MapKit
struct MapLandmark: Codable {
let placemark: MKPlacemark
var id: UUID {
return UUID()
}
var name: String {
self.placemark.name ?? ""
}
var title: String {
self.placemark.title ?? ""
}
var coordinate: CLLocationCoordinate2D {
self.placemark.coordinate
}
}
Я попытался добавить классы кодирования и декодирования из приведенной выше ссылки, но продолжаю сталкиваться с ошибками. Каков наилучший способ реализации решения?
РЕДАКТИРОВАТЬ: я забыл упомянуть ошибки, которые я получаю:
«Тип ‘MapLandmark’ не соответствует протоколу ‘Decodable'»
«Тип ‘MapLandmark’ не соответствует протоколу ‘Encodable»
Комментарии:
1. При запросе помощи с ошибками всегда, всегда указывайте текст ошибок. Мы не сможем помочь вам решить проблему, если мы не знаем, в чем конкретно она заключается.
2. поместите:Codable после имени вашего класса, чтобы оно соответствовало
3. @Caleb Извините за ошибку, я включил сообщение об ошибке в комментарий выше и вскоре отредактирую свой пост.
4. @gcharita Это Firebase / Firestore
5. MKPlacemark не соответствует Codable, поэтому вы не можете использовать его (напрямую) в своей структуре, поскольку все свойства кодируемого типа должны соответствовать Codable
Ответ №1:
MKPlacemark
соответствует NSSecureCoding
. Вы можете просто использовать NSKeyedArchiver
и NSKeyedUnarchiver
для его кодирования / декодирования. UUID
уже соответствует Codable
. Попробуйте выполнить следующее:
import MapKit
extension NSSecureCoding {
func archived() throws -> Data {
try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
}
extension Data {
func unarchived<T: NSSecureCoding>() throws -> T? {
try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(self) as? T
}
}
struct MapLandmark: Codable {
let placemark: MKPlacemark
let id: UUID
func encode(to encoder: Encoder) throws {
var unkeyedContainer = encoder.unkeyedContainer()
try unkeyedContainer.encode(placemark.archived())
try unkeyedContainer.encode(id)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
placemark = try container.decode(Data.self).unarchived()!
id = try container.decode(UUID.self)
}
}
Комментарии:
1. Спасибо, Лео! Это очень помогло
2. Извините, Лео, у меня быстрый последующий вопрос. Как мне использовать функцию encode для кодирования объекта MapLandmark? Спасибо
3. Неважно, я понял, что неправильно подхожу к этому, и использовал MapLandmark.encode()