Programación en Swift y SwiftUI para iOS Developers

Que es el protocolo Identifiable en Swift y en SwiftUI

Identifiable es un protocolo en Swift que obliga a los tipos a incluir una propiedad de identificador única. Este identificador ayuda a diferenciar instancias individuales de tipo entre ellas dentro de arrays o colecciones.

Vamos a ver con un ejemplo cuando puede ser util el protocolo Identifiable. Si tenemos este código:

struct ContentView: View {
    var body: some View {
        
        var restaurants = [ Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
                       Restaurant(name: "Homei", image: "homei"),
                       Restaurant(name: "Teakha", image: "teakha"),
                       Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
                       Restaurant(name: "Teakha", image: "petiteoyster"),
                            Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant"), Restaurant(name: "Po's Atelier", image: "posatelier"), Restaurant(name: "Bourke Street Bakery", image: "bourkestreetbakery"), Restaurant(name: "Haigh's Chocolate", image: "haighschocolate")]
        

        var restaurantImages = ["cafedeadend", "homei", "teakha", "cafeloisl", "petiteoyster", "forkeerestaurant", "posatelier", "bourkestreetbakery", "haighschocolate"]
    
        List(restaurants, id: \.name) { restaurant in
            
            HStack {
                
                Image(restaurant.image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(5)
                Text(restaurant.name)
     
            }
        }
        .listStyle(.plain)
    }
}

struct Restaurant {
    
    var name: String
    var image: String
}

Echa un vistazo al código en Swift y a los parámetros que pasamos a List. Pasamos el array restaurants y especificamos la propiedad name como el identificador para cada restaurante. List iterará por el array y nos proporcionará el actual restaurante. Dentro del HStack especificamos como queremos que sea mostrado cada fila del restaurante. En este caso mostramos una imagen y el nombre del restaurante.

Si te fijas bien hay dos restaurantes con el mismo nombre y como resultado los dos mostrarán la misma imagen. Y lo que no queremos es que se muestre la misma imagen para ambos restaurantes. En la siguiente imagen puedes ver como ambos restaurantes muestran el mismo nombre y la misma imagen:

Podemos ver como el restaurante “Teakha” muestra la misma imagen.

En el código le hemos dicho a List que use la propiedad name como el identificador único. Sin embargo cuando dos restaurantes tienen el mismo nombre, iOS considera que los restaurantes son los mismos y reusa la vista.

Por lo tanto, como arreglamos esto?

Solo necesitamos proporcionar a cada restaurante un identificador único. Vamos a actualizar la struct Restaurant añadiendo una propiedad llamada id del tipo UUID. Eso asegurará que cada restaurante tenga un identificador único. Aquí está el código actualizado:

struct Restaurant {
    
    var id = UUID()
    var name: String
    var image: String
}

En el código hemos añadido hemos añadido un propiedad id a la struct Restaurant y la hemos inicilizado con un identificador único usando la función UUID(). Esto asegura que cada restaurante tiene una ID única. Un UUID esta compuesto de un número de 128-bit, así que teóricamente la probabilidad de tener dos identificadores iguales es casi cero.

Para hacer que todo funcione correctamente tenemos que actualizar la vista List cambiándooslo el parámetro \.name por \.id. Esto le dice a List que tiene que usar la propiedad id de cada restaurante como el identificador.

El código quedaría de la siguiente manera:

struct ContentView: View {
    var body: some View {
        
        var restaurants = [ Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
                       Restaurant(name: "Homei", image: "homei"),
                       Restaurant(name: "Teakha", image: "teakha"),
                       Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
                       Restaurant(name: "Teakha", image: "petiteoyster"),
                            Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant"), Restaurant(name: "Po's Atelier", image: "posatelier"), Restaurant(name: "Bourke Street Bakery", image: "bourkestreetbakery"), Restaurant(name: "Haigh's Chocolate", image: "haighschocolate")]
        

        var restaurantImages = ["cafedeadend", "homei", "teakha", "cafeloisl", "petiteoyster", "forkeerestaurant", "posatelier", "bourkestreetbakery", "haighschocolate"]
    
        List(restaurants, id: \.id) { restaurant in
            
            HStack {
                
                Image(restaurant.image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(5)
                Text(restaurant.name)
     
            }
        }
        .listStyle(.plain)
    }
}

struct Restaurant {
    
    var id = UUID()
    var name: String
    var image: String
}

En la siguiente imagen puedes ver como ahora el segundo restaurante Teakha muestra una imagen diferente y correcta:

Como cumplir con el protocolo Identifiable

Podemos simplificar el código haciendo que la struct Restaurant conforme al protocolo Identifiable, el cual tiene solo un requisito: el tipo que implemente el protocolo tiene que tener un tipo de id como identificador único.

Vamos a actualizar la struct Restaurant para conformar al protocolo Identifiable de la siguiente manera:

struct Restaurant:Identifiable {
    
    var id = UUID()
    var name: String
    var image: String
}

Ya que la struct Restaurant tiene una única propiedad id, conforma al requisito del protocolo y de esta manera podemos inicializar List sin la necesidad de especificar explicitamente un parámetro id. Esto simplifica mucho el código. Aquí está el código actualizado:

struct ContentView: View {
    var body: some View {
        
        var restaurants = [ Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
                       Restaurant(name: "Homei", image: "homei"),
                       Restaurant(name: "Teakha", image: "teakha"),
                       Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
                       Restaurant(name: "Teakha", image: "petiteoyster"),
                            Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant"), Restaurant(name: "Po's Atelier", image: "posatelier"), Restaurant(name: "Bourke Street Bakery", image: "bourkestreetbakery"), Restaurant(name: "Haigh's Chocolate", image: "haighschocolate")]
        

        var restaurantImages = ["cafedeadend", "homei", "teakha", "cafeloisl", "petiteoyster", "forkeerestaurant", "posatelier", "bourkestreetbakery", "haighschocolate"]
    
        List(restaurants) { restaurant in
            
            HStack {
                
                Image(restaurant.image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(5)
                Text(restaurant.name)
     
            }
        }
        .listStyle(.plain)
    }
}

struct Restaurant:Identifiable {
    
    var id = UUID()
    var name: String
    var image: String
}


Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

Como crear una Lista o tabla con texto e imagenes en SwiftUI

Next Article

Como cambiar el color de una línea separadora de tabla o lista en SwiftUI

Related Posts