我会使用nodesWithDepth个可解码的:

这在以前很管用:

public struct NEWTREE: Equatable, Codable {
    public var Filename: String
    public var GROUP: [GROUP]
    public var ITEM: [ITEM]
    public var CATEGORY: [CATEGORY]
    public var ROOT: ROOT

但修改后的不是:

public struct NEWTREE: Equatable, Codable {
    public var Filename: String
    public var GROUP: [GROUP]
    public var ITEM: [ITEM]
    public var CATEGORY: [CATEGORY]
    public var ROOT: ROOT
    public var nodesWithDepth: [(text: String, depth: Int, type: TreeData2)]?
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        Filename = try container.decode(String.self, forKey: .Filename)
        GROUP = try container.decode([GROUP].self, forKey: .GROUP)
        ITEM = try container.decode([ITEM].self, forKey: .ITEM)
        CATEGORY = try container.decode([CATEGORY].self, forKey: .CATEGORY)
        ROOT = try container.decode(ROOT.self, forKey: .ROOT)
    }
    
    private enum CodingKeys: String, CodingKey {
        case Filename
        case GROUP
        case ITEM
        case CATEGORY
        case ROOT
    }

但这引发了一个错误:

无法将类型为‘[[group]]’的值转换为预期的参数类型‘[group].Type’

我怎么才能修好?

推荐答案

SWIFT对以下表述感到困惑

[GROUP].self

显然,编译器认为这里的GROUP指的是属性GROUP,而不是类型GROUP.Note that it is totally valid to add .self to any expression,,而不改变它的含义.

因此,您实际上是在传递一个单元素数组,其中包含属性GROUP的值.该表达式的类型为[[GROUP]],但decode显然需要一个可解码的元类型,因此出现错误.

或者在ROOT的情况下,您传递的是ROOT属性的值,该属性的类型为ROOT,但decode显然需要一个可解码的元类型.

这种行为可以用一个更小的例子来展示,如下所示:

struct A {}
struct B {
    let A: A

    func f() {
        print(A.self)
        print([A].self)
    }
}

B(A: A()).f()
print("-------")
print(A.self)
print([A].self)

B之外的两个print语句打印元类型,而B内的两个print语句打印A的实例和一个array.


您可以通过使用数组类型的长格式Array<Group>.self来解决这种多义性

GROUP = try container.decode(Array<GROUP>.self, forKey: .GROUP)

或者在类似ROOT的情况下引入类型别名:

typealias ROOTType = ROOT

...

ROOT = try container.decode(ROOTType.self, forKey: .ROOT)

但当然,如果你遵循SWIFT命名指南,并做到了这一点,这一切都不会发生:

var groups: [Group]

如果希望编码键全部大写,可以在编码键枚举中执行此操作:

public struct NewTree: Equatable, Codable {
    public var filename: String
    public var groups: [Group]
    public var items: [Item]
    public var categories: [Category]
    public var root: Root

    // consider making the tuple here into another struct...
    public var nodesWithDepth: [(text: String, depth: Int, type: TreeData2)]?

    // you don't actually need to write the custom decoding logic just because you added nodesWithDepth
    // Swift can figure it out from the CodingKeys enum because the
    // case names match the property names

    private enum CodingKeys: String, CodingKey {
        case filename = "Filename"
        case groups = "GROUP"
        case items = "ITEM"
        case categories = "CATEGORY"
        case root = "ROOT"
    }
}

Swift相关问答推荐

SwiftUI map 旋转

并发访问SWIFT中数组的非重叠子范围

UICollectionViewCompostionalLayout Collectionview单元格宽度在重新加载数据后未正确调整大小

我需要一些关于 SwiftUI 动画的帮助

计算 CoreData 中所有唯一对象的数量?

UIImage和UIimage.pngData返回两个不同的图像

为什么我在我的 Swift iOS 应用程序项目中收到 Xcode 中的错误消息无法识别的 Select 器发送到类?

将 Encodable 扩展添加到 Swift 嵌套枚举

如何将变量添加到不属于可解码部分的 struct ?

用逻辑运算符保护让

UUID 哈希值是不确定的吗?

如何在 SwiftUI 的 fileImporter 中为 allowedContentTypes 设置 xcodeproj 类型?

调用从 SwiftUI 视图传递到 PageViewController.Coordinator 的函数

Xcode 7.3 Swift 的语法高亮和代码完成问题

Swift 自定义字体 Xcode

iOS/Swift:如何检测 UITextField 上的touch 动作

Alamofire:如何全局处理错误

如何在 SwiftUI 中的一个视图上显示两个alert ?

如何判断 firebase 数据库值是否存在?

iPhone 纵向和 iPad 横向的通用应用程序