【问题标题】:Implementing Codable for ARAnchor: "cannot be automatically synthesized in an extension..."为 ARAnchor 实现 Codable:“无法在扩展中自动合成……”
【发布时间】:2019-04-14 16:41:28
【问题描述】:

代码extension ARAnchor: Codable {} 产生错误:

“'Decodable' 的实现不能自动合成到与该类型不同的文件的扩展中”。

这是什么意思?我能够以类似的方式为另一种原生类型实现 Codable 而没有任何错误。

【问题讨论】:

  • in an extension in a different file to the type 您成功的扩展名是否在同一个文件中?
  • 不,它是针对自己文件中的另一个原生类型

标签: swift augmented-reality arkit codable


【解决方案1】:

您可以创建一个实现Codable 的容器对象,然后使用它对锚点进行编码和解码。我在操场上尝试了这段代码,它对我有用。您需要调整它以适应您想要从锚点获得的数据;例如,我对name 进行了编码,但这对您来说可能没用,如果您的锚点在没有名称的情况下初始化,它甚至可能会中断。你也可以用simd_float4x4 做同样的事情。

import Foundation
import ARKit

class AnchorContainer: Codable {
    
    let anchor: ARAnchor
    
    init(anchor: ARAnchor) {
        self.anchor = anchor
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let name = try container.decode(String.self, forKey: .name)
        let transform0 = try container.decode(simd_float4.self, forKey: .transform0)
        let transform1 = try container.decode(simd_float4.self, forKey: .transform1)
        let transform2 = try container.decode(simd_float4.self, forKey: .transform2)
        let transform3 = try container.decode(simd_float4.self, forKey: .transform3)
        let matrix = simd_float4x4(columns: (transform0, transform1, transform2, transform3))
        anchor = ARAnchor(name: name, transform: matrix)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(anchor.name, forKey: .name) // Might want to make sure that the name is not nil here
        try container.encode(anchor.transform.columns.0, forKey: .transform0)
        try container.encode(anchor.transform.columns.1, forKey: .transform1)
        try container.encode(anchor.transform.columns.2, forKey: .transform2)
        try container.encode(anchor.transform.columns.3, forKey: .transform3)
    }
    
    enum CodingKeys: String, CodingKey {
        case name
        case transform0
        case transform1
        case transform2
        case transform3
    }
    
}

// EXAMPLE:

let anchor = ARAnchor(name: "Bill", transform: simd_float4x4(float4(repeating: 4), float4(repeating: 5), float4(repeating: 6), float4(repeating: 7))) // Make a arbitrary anchor
print(anchor) // Figure out what it's value is


do {
    let data = try JSONEncoder().encode(AnchorContainer(anchor: anchor))
    let anchorDecode = try JSONDecoder().decode(AnchorContainer.self, from: data)
    print(anchorDecode.anchor) // Print the value after decoding to make sure that the result is the same
} catch {
    print(error.localizedDescription)
}

【讨论】:

  • 分解矩阵很有意义。我正在探索该选项是 simd_float4x4 是导致编码问题的类型。这太棒了!
【解决方案2】:

Swift 编译器 AFAICT 目前不支持在不同的源文件中综合符合 CodableEquatableHashable。有关跟踪此问题的问题,请参阅 https://bugs.swift.org/browse/SR-6101

【讨论】:

  • 哇,一定有解决方法吗?不支持的原生类型如何添加 Codable?
  • 我相信你现在不能,至少不能让编译器合成它。不过,实现init(coder:)decode(from:) 仍然是一种选择。
【解决方案3】:

由于CodableEncodableDecodable 协议的类型别名,当您将其用作类型通用约束,它匹配任何符合这两种协议的类型:

public typealias Codable = Decodable & Encodable

目前 (Xcode 10.2.1 / Swift 5.0.1) Codable 目前尚不支持,如果一个文件中的扩展在另一个文件中添加一致性。请通过https://bugs.swift.org/查看此内容。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多