¿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.
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:
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.