【问题标题】:Making CLCircularRegion Codable使 CLCircularRegion 可编码
【发布时间】:2020-03-05 18:42:56
【问题描述】:

我正在尝试(在操场上)使 CLCircularRegion 可编码。但是我有一个无法修复的错误:错误:初始化程序要求“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)
    }
}

【问题讨论】:

    标签: swift codable


    【解决方案1】:

    一种解决方案是将类包装在符合 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)
        }
    }
    

    【讨论】:

      【解决方案2】:

      你不能这样做。 CLCircularRegion 不是 final 类。当你扩展一个非最终类时,你只能在扩展中编写 convenience 初始化器。 Decodable 指定初始化器必须声明为required

      但我们刚刚看到你不能这样做,因为 Swift 不允许你在扩展中声明 required 初始化器。

      顺便说一句,一般来说,扩展其他人的类型以使其符合Codable 并不是一个好主意,因为在未来某个时候,编写该类型的人也可能会添加Codable 一致性,而且很可能他们的实现与您的实现不匹配,这将导致一些难以诊断的错误。

      如前所述,最好的办法是将CLCircularRegion 包装在符合Codable 的结构中。

      【讨论】:

        猜你喜欢
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-28
        • 1970-01-01
        • 1970-01-01
        • 2015-01-16
        相关资源
        最近更新 更多