Post

Simplificando la inicialización en las vistas en SwiftUI

Cuando  creamos componentes reutilizables de las vistas de SwiftUI podemos añadir la versatilidad que nos dan los inicializadores (inits) en los structs.

Los structs tienen su inicializador por defecto, pero podemos añadir todos los que deseemos.

En este ejemplo de una celda con varios parámetros:

struct RatingCell: View {
    let day: String
    let month: String
    let title: String
    let subtitle: String
    let namespace: Namespace.ID
    
    var body: some View {
        HStack(alignment: .center, spacing: 20) {
            VStack {
                Text(day)
                    .fontStyle(.subtitle, bold: true)
                Text(month)
                    .fontStyle(.headline, color: .gray)
            }
            VStack(alignment:.leading) {
                Text(title)
                //Resto de la implementación...
            }
        }
    }
}

Gracias a las extensiones podemos crear inits a los que pasar valores a los parámetros de una subsista.

extension RatingCell {
    init(activity: Activity, namespace: Namespace.ID) {
        day = activity.dayView
        month = activity.monthView
        title = activity.hintView
        subtitle = activity.comments
        self.namespace = namespace
    }
    
    init(daily: Daily, namespace: Namespace.ID) {
        day = daily.dayView
        month = daily.monthView
        title = daily.instructions
        subtitle = daily.details
        self.namespace = namespace
    }
}

Ventajas:

  • Tendremos una interfaz más fluida
  • La vista conserva el inicializador por defecto
  • La vista está desacoplada del modelo

struct ActivityRatingListView: View {
    let activities: [Activity]
    let selectedActivity: Activity?
    let namespace: Namespace.ID
    let cols: GridItem = [GridItem()]
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: cols) {
                ForEach(activities) { activity  in
                    Button {
                        selectedActivity = activity
                    } label: {
                        RatingCell(activity: activity, namespace: namespace)
                    }
                }
            }
        }
    }
}