Creación de Componentes Reutilizables con @Binding en SwiftUI

Clase 19 de 23Curso de Desarrollo de Aplicaciones con SwiftUI

Clase 19: Creación de Componentes Reutilizables con @Binding

En esta clase aprenderás qué es @Binding y cómo usarlo para conectar datos entre vistas. También modularizaremos el código del formulario creando un componente reutilizable llamado NTextField. Este componente reutilizará el diseño existente en el formulario, ayudándote a optimizar y mantener tu código limpio y organizado.

1. ¿Qué es @Binding?

El Binding en SwiftUI es un lazo bidireccional que conecta datos entre una vista y su vista contenedora. Permite que los cambios realizados en una subvista se reflejen automáticamente en la vista que la contiene, y viceversa.

Ejemplo Conceptual

struct ParentView: View { @State private var text: String = "" var body: some View { ChildView(text: $text) // Pasamos el Binding } } struct ChildView: View { @Binding var text: String // Recibimos el Binding var body: some View { TextField("Escribe algo...", text: $text) } }

En este ejemplo:

  • ParentView tiene una propiedad @State llamada text.
  • La subvista ChildView utiliza un @Binding para sincronizarse con ParentView.

2. Refactorizando con NTextField

El formulario original tenía un TextField con un diseño definido directamente en la vista. Reutilizaremos ese mismo diseño en un nuevo componente llamado NTextField.

Formulario Original

En el formulario original, el TextField estaba diseñado así:

TextField("Título", text: $viewModel.title) .font(.headline) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8)

Este diseño será la base para nuestro componente reutilizable.


Creando NTextField

El componente NTextField encapsula el diseño y la funcionalidad del TextField original, permitiendo su reutilización en otras partes de la aplicación.

import SwiftUI struct NTextField: View { let placeholder: String @Binding var text: String var body: some View { // Reutilizamos el diseño del formulario original TextField(placeholder, text: $text) .font(.headline) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8) } } #Preview { VStack { NTextField(placeholder: "Escribe algo...", text: .constant("Texto inicial")) NTextField(placeholder: "Escribe algo más...", text: .constant("")) } .padding() }

Ventajas del Componente Reutilizable

  1. Consistencia:
    • Asegura que todos los TextField sigan el mismo estilo.
  2. Modularidad:
    • Si el diseño cambia en el futuro, puedes actualizarlo desde un solo lugar.
  3. Claridad:
    • Reduce el código repetido en tus vistas.

3. Actualizando el Formulario con NTextField

Reemplazaremos el TextField en el formulario por el nuevo componente NTextField.

Formulario Original

TextField("Título", text: $viewModel.title) .font(.headline) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8)

Formulario Refactorizado

Usaremos el NTextField para simplificar el código:

NTextField(placeholder: "Título", text: $viewModel.title)

Formulario Completo

El formulario queda así después del refactor:

struct NCreateNoteView: View { @StateObject var viewModel: NCreateNoteViewModel = NCreateNoteViewModel() var onNoteCreated: ((NCard) -> Void)? func onTap() { let card = viewModel.createNote() print("Esta es tu nueva card: \\(card)") onNoteCreated?(card) } var body: some View { ScrollView { VStack { Text("Crear Nueva Nota") .font(.largeTitle) .bold() .padding(.bottom, 10) // Usamos el componente reutilizable NTextField(placeholder: "Título", text: $viewModel.title) TextEditor(text: $viewModel.text) .scrollContentBackground(.hidden) .font(.body) .frame(height: 150) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8) HStack { Text("Tamaño") Spacer() Picker("Tamaños", selection: $viewModel.size) { Text("Pequeño").tag(NCardType.small) Text("Mediano").tag(NCardType.medium) } } .padding() Toggle("Marcar como favorito", isOn: $viewModel.isFavorite) .padding() Button { onTap() } label: { Text("Guardar Nota") .font(.headline) .foregroundStyle(Color.white) .frame(maxWidth: .infinity) .padding() .background(Color.blue) .cornerRadius(8) } .padding(.top, 20) } } .padding() .background(Color.white) .cornerRadius(16) .padding() .background(Color.cyan.opacity(0.2)) } } #Preview { NCreateNoteView() }

4. Reto: Crear NTextEditor

Usando los mismos conceptos, crea un componente reutilizable para el TextEditor llamado NTextEditor.

Ejemplo de NTextEditor

struct NTextEditor: View { @Binding var text: String var body: some View { TextEditor(text: $text) .scrollContentBackground(.hidden) .font(.body) .frame(height: 150) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8) } }

Reemplaza el TextEditor del formulario por:

NTextEditor(text: $viewModel.text)

5. Conclusión

En esta clase aprendiste:

  1. Qué es y cómo funciona @Binding.
  2. Cómo crear componentes reutilizables como NTextField.
  3. Cómo refactorizar tu código para hacerlo más modular y consistente.

Tu reto:

Refactoriza el TextEditor usando @Binding y crea un componente llamado NTextEditor. Esto consolidará tus habilidades en el uso de @Binding y la creación de componentes reutilizables.

¡Compártelo en los comentarios para que otros estudiantes también puedan aprender de tus avances!