es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué borrar un NavigationLink después de haber visitado recientemente causa un fallo en la aplicación?

El siguiente es un proyecto que creé para demostrar mi problema. Cada vez que hago clic y veo un enlace de navegación desde la vista de contenido y luego lo elimino de la vista de contenido, la aplicación se bloquea con el error “Thread 1: Fatal error: Encontró inesperadamente nil mientras desenvolvía un valor opcional” en la línea 5 de mi vista secundaria.

Mi vista de contenido:

struct ContentView: View {
    @ObservedObject var ingredientViewModel = IngredientViewModel()
    private func deleteIngredient(with indexSet:IndexSet) {
        ingredientViewModel.ingredients.remove(atOffsets: indexSet)
    }
    var body: some View {
        NavigationView {
            List {
                ForEach(ingredientViewModel.ingredients) { ingredient in
                    NavigationLink(destination: IngreidentView(ingredientId: ingredient.id).environmentObject(ingredientViewModel)) {
                        Text(ingredient.name)
                    }
                }.onDelete(perform: deleteIngredient)
            }
        }
    }
}

Mi modelo de vista:

class IngredientViewModel: ObservableObject {
    @Published
    var ingredients: [Ingredient] = [Ingredient(name: "Orange", amount: 5),Ingredient(name: "Potato", amount: 3),Ingredient(name: "Tomato",amount: 1),Ingredient(name: "Salt",amount: 2)]
}

Mi modelo de ingrediente:

struct Ingredient: Identifiable {
    var name: String
    var amount: Int
    var id = UUID().uuidString
}

Mi vista secundaria en el enlace de navegación:

struct IngreidentView: View {
    @EnvironmentObject var db: IngredientViewModel
    var ingredientId: String
    private var ingredient: Ingredient {
        db.ingredients.filter {$0.id == ingredientId}.first!
    }
    var body: some View {
        if(ingredient.amount == 0) {
            Text("¡Cantidad igual a 0!")
        } else {
            Text("\(ingredient.amount) cantidad")
        }
    }
}

Utilicé una propiedad computada para obtener el ingrediente en mi vista secundaria ya que anticipé que el ingrediente cambiaría y quiero que se actualice desde la base de datos.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Descripción del problema

    La aplicación se bloquea con el error “Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value” en la línea 5 de la Vista Hija. Esto sucede cada vez que se hace clic en un Navigation Link y se visualiza desde la Vista de Contenido, y luego se elimina desde la Vista de Contenido.

    Solución

    El problema se debe a que la vista hija aún está intentando acceder al ingrediente eliminado de la base de datos, incluso después de haberlo eliminado de la lista en la Vista de Contenido. Para solucionarlo, debes actualizar la vista hija para manejar el caso en el que el ingrediente ya no exista en la base de datos.

    Aquí tienes una versión actualizada de la Vista Hija que verifica si se puede obtener el ingrediente de la base de datos antes de intentar usarlo:

    struct IngreidentView: View {
        @EnvironmentObject var db: IngredientViewModel
        var ingredientId: String
        private var ingredient: Ingredient? {
            db.ingredients.filter {$0.id == ingredientId}.first
        }
        var body: some View {
            if let ingredient = ingredient {
                if(ingredient.amount == 0) {
                    Text("¡Cantidad 0!")
                } else {
                    Text("\(ingredient.amount) cantidad")
                }
            } else {
                Text("¡Ingrediente no encontrado!")
            }
        }
    }
    

    Observa que la propiedad ingredient ahora es opcional y la sentencia if verifica si existe antes de usarla. Si el ingrediente no se encuentra, la vista muestra un mensaje indicando que no se ha encontrado.

    Con este cambio, la aplicación ya no debería bloquearse cuando se elimina un Navigation Link desde la Vista de Contenido.

Comments are closed.