Создание CLCircularRegion Codable - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь (на детской площадке) сделать CLCircularRegion Codable. Но у меня есть ошибка, которую я не могу исправить: ошибка: требование инициализатора 'init (from :)' может быть удовлетворено только 'обязательным' инициализатором в определении не финального класса 'CLCircularRegion'. Есть идеи?

import UIKit
import MapKit

// MARK: - CLLocationCoordinate2D

extension CLLocationCoordinate2D: Codable {

    public func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(longitude)
        try container.encode(latitude)
    }

    public init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let longitude = try container.decode(CLLocationDegrees.self)
        let latitude = try container.decode(CLLocationDegrees.self)
        self.init(latitude: latitude, longitude: longitude)
    }
}

// MARK: - CLLocationCoordinate2D

extension CLCircularRegion : Codable {

    public func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(identifier)
        try container.encode(center)
        try container.encode(radius)
    }

    public required init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let identifier = try container.decode(String.self)
        let center = try container.decode(CLLocationCoordinate2D.self)
        let radius = try container.decode(CLLocationDistance.self)

        self.init(center: center, radius: radius, identifier: identifier)
    }
}

let coordinate = CLLocationCoordinate2D(latitude: 45.123, longitude: 5.678)
let region = CLCircularRegion(center: coordinate, radius: 100, identifier: "identifierTest")

// encode
if let jsonData = try? JSONEncoder().encode(region), let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)

    // decode
    if let decodedRegion = try? JSONDecoder().decode(CLCircularRegion.self, from: jsonData) {
        print(decodedRegion)
    }
}

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Вы не можете сделать это. CLCircularRegion не является final классом. Когда вы расширяете неконечный класс, вы можете писать только convenience инициализаторы в расширении. Decodable указывает, что инициализатор должен быть объявлен required.

Но мы только что увидели, что вы не можете этого сделать, потому что Swift не позволяет вам объявлять required инициализаторы в расширении.

В целом, это не очень хорошо идея расширить чужие типы, чтобы привести их в соответствие с Codable, потому что в будущем тот, кто написал тип, может также добавить соответствие Codable, и очень вероятно, что их реализация не будет соответствовать вашей реализации, что вызовет некоторые ошибки это будет очень трудно диагностировать.

Как уже упоминалось, лучше всего заключить оболочку CLCircularRegion в структуру, которая соответствует Codable.

1 голос
/ 05 марта 2020

Одно из решений - обернуть класс в структуру, которая соответствует Codable

struct CodableCircularRegion : Codable {
    var region: CLCircularRegion?
    public func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(region?.identifier)
        try container.encode(region?.center)
        try container.encode(region?.radius)
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let identifier = try container.decode(String.self)
        let center = try container.decode(CLLocationCoordinate2D.self)
        let radius = try container.decode(CLLocationDistance.self)

        region = CLCircularRegion(center: center, radius: radius, identifier: identifier)
    }

    init(_ region: CLCircularRegion) {
        self.region = region
    }
}

Кодировка / декодирование практически одинаковы

if let jsonData = try? JSONEncoder().encode(CodableCircularRegion(region)), let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)

    // decode
    if let decodedRegion = try? JSONDecoder().decode(CodableCircularRegion.self, from: jsonData) {
        print(decodedRegion.region)
    }
}
...