我正在通过CloudKit使用核心数据,我想要做的是将数据从那里导出到文件中.任何项都可以具有子项,这意味着子项可以具有子项,这意味着项可以是任意数量的嵌套级别.我的问题是,我不知道如何获取嵌套项的路径,以便将其子项添加到itemEntry数组中.我的另一个问题是,即使我确实有一个名为pathToItem的变量,具有正确的路径,如[0][0][0],我也不知道如何使用该变量来更新itemEntry数组,因为我假设itemEntries[pathToItem]不起作用.


    @State private var itemEntries: [ItemEntry] = []
    
    struct ItemEntry: Codable {
        var title: String
        var children: [ItemEntry]
    }
    
    private func populateNestedData(items: [Item], itemsAreNested: Bool = false) {
        for item in items {
            if (!itemsAreNested) {
                itemEntries.append(createItemEntry(item: item))
            }
            else {
              //Here is my problem. The item could be any number of levels nested. How can I get the path to the item so that I can use it to append the child item to the itemEntries array?
                let pathToItem = ?????
              //And even if I did have pathToItem such as [0][0][0] how would I then use that correctly here?
                itemEntries[pathToItem].children.append(createItemEntry(item: item))
            }
            
            if (!item.childrenArray.isEmpty) {
                var children = coreDataController.getChildrenOfItemForExporting(item: item)
                populateNestedData(items: children, itemsAreNested: true)
            }
        }
    }
    
    private func createItemEntry(item: Item) -> ItemEntry {
        return ItemEntry(
            title: item.title ?? "",
            children: []
        )
    }

推荐答案

如果我没记错的话,你要找的是key paths美元.它们表示获取/设置类型的属性的"路径",或数组的索引.

键路径将表示您要追加到的array.在每次递归调用中,您都会一直附加到它后面,以"深入一层".最初,它是\.self,代表一条"空"路径.

private func populateNestedData(items: [Item], keyPath: WritableKeyPath<[ItemEntry], [ItemEntry]> = \.self) {
    for item in items {
        // itemEntries[keyPath: \.self] is the same as itemEntries
        // so you can get rid of the itemsAreNested parameter
        itemEntries[keyPath: keyPath].append(createItemEntry(item: item))
        
        if (!item.childrenArray.isEmpty) {
            let children = ...
            // this is the index of the last item inserted into itemEntries[keyPath: keyPath]
            let lastInsertedIndex = itemEntries[keyPath: keyPath].count - 1
            populateNestedData(
                items: children,
                // appends the key path representing the children of the item last inserted to itemEntries[keyPath: keyPath]
                keyPath: keyPath.appending(path: \.[lastInsertedIndex].children)
            )
        }
    }
}

也就是说,我认为最好将其编写为返回[ItemEntry]的函数:

private func populateNestedData(items: [Item]) -> [ItemEntry] {
    var entries = [ItemEntry]()
    for item in items {
        var itemEntry = createItemEntry(item: item)
        
        if (!item.childrenArray.isEmpty) {
            let children = ...
            itemEntry.children = populateNestedData(items: children)
        }
        entries.append(itemEntry)
    }
    return entries
}

当您想要调用此命令时,并将其分配给itemEntries状态:

itemEntries = populateNestedData(items: ...)

Swift相关问答推荐

如何使用swift宏生成一个带有关联值的枚举?

如何在向照片添加文本时定义文本对齐、文本背景的Alpha和在文本之前添加图像

避免嵌套导航TabView

background Task(.backgroundTask)不适用于MySQL

如何写一个;风格;视图修饰符,它会影响特定类型的所有嵌套视图?

VisionOS TabBar预览中是否存在漏洞?

从 actor 的 init 方法调用方法

Swift 包管理器 Package.resolved 文件末尾的版本是什么意思?

使 Picker 与其他 BinaryInteger 类型兼容

您可以在运行时访问 Picker 元素并更改它们的 colored颜色 吗

如何从 LLDB 调用带有断点的 Swift 函数?

swift中的SequenceType和CollectionType有什么区别?

swift 3 错误:参数标签 '(_:)' 不匹配任何可用的重载

根据禁用与否更改 SwiftUI 中按钮的 colored颜色

swift : 具有类型和值的枚举常量

try 在解除分配时加载视图控制器的视图... UIAlertController

在 Swift 中,你可以用另一个字符串分割一个字符串,而不仅仅是一个字符吗?

如何在 GCD 中停止 DispatchWorkItem?

如何发送静默推送通知有效负载

如何快速格式化用户显示(社交网络等)的时间间隔?