Swift - 如何更新多维目录中的对象

Swift - How to update object in multi-dimensional directory

我希望能够在这些对象的数组中找到并更新自定义对象。挑战在于自定义对象也可以是对象的子对象。

自定义对象如下所示:

class CustomObject: NSObject {
    var id: String?
    var title: String?
    var childObjects: [CustomObject]?
}

我希望能够创建一个函数来覆盖具有特定 ID 的自定义对象,如下所示:

 var allCustomObjects: [CustomObject]?
    
 func updateCustomObject(withId id: String, newCustomObject: CustomObject) {
        
     var updatedAllCustomObjects = allCustomObjects
        
     // ...
     // find and update the specific custom object with the id
     // ...
        
     allCustomObjects = updatedAllCustomObjects
 }

我认识到这对于 Swift 和其他语言的多维数组/目录来说一定是一个非常正常的问题。请让我知道这个问题的常规做法是什么。

与大多数与树有关的事情一样,递归会有所帮助。您可以添加一个额外的参数,指示您当前正在经历的 CustomObject 数组,以及 returns 一个 Bool 指示是否找到 ID,用于 short-circuiting 目的.

@discardableResult
func updateCustomObject(withId id: String, in objectsOrNil: inout [CustomObject]?, newCustomObject: CustomObject) -> Bool {
    guard let objects = objectsOrNil else { return false }
    if let index = objects.firstIndex(where: { [=10=].id == id }) {
        // base case: if we can find the ID directly in the array passed in
        objectsOrNil?[index] = newCustomObject
        return true
    } else { 
        // recursive case: we need to do the same thing for the children of
        // each of the objects in the array
        for obj in objects {
            // if an update is successful, we can end the loop there!
            if updateCustomObject(withId: id, in: &obj.childObjects, newCustomObject: newCustomObject) {
                return true
            }
        }
        return false
        // technically I think you can also replace the loop with a call to "contains":
        // return objects.contains(where: { 
        //     updateCustomObject(withId: id, in: &[=10=].childObjects, newCustomObject: newCustomObject) 
        //  })
        // but I don't like doing that because updateCustomObject has side effects
    }
}

您可以这样称呼它,in: 参数为 allCustomObjects

updateCustomObject(withId: "...", in: &allCustomObjects, newCustomObject: ...)