Quiero poder encontrar y actualizar un objeto personalizado en una matriz de estos objetos. El desafío es que los objetos personalizados también pueden ser hijos del objeto.
El objeto personalizado se ve así:
class CustomObject: NSObject { var id: String? var title: String? var childObjects: [CustomObject]? }Me gustaría poder crear una función que sobrescriba el objeto personalizado con fx una ID específica, como esta:
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 }Reconozco que esto debe ser un problema bastante normal con respecto a matrices/directorios multidimensionales tanto en Swift como en otros idiomas. Por favor, hágame saber qué práctica normal se utiliza para este problema.
Como con la mayoría de las cosas relacionadas con los árboles, la recursividad ayudará. Puede agregar un parámetro adicional que indique qué matriz de CustomObject s está revisando actualmente y devuelve un Bool que indica si se encuentra la ID, para fines de cortocircuito.
@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: { $0.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: &$0.childObjects, newCustomObject: newCustomObject) // }) // but I don't like doing that because updateCustomObject has side effects } } Llamaría a esto así, con el parámetro in: siendo allCustomObjects .
updateCustomObject(withId: "...", in: &allCustomObjects, newCustomObject: ...)