SwiftUI: componente EmptyView

Qué es EmptyView

El componente EmptyView permite devolver una vista vacía que no tiene representación gráfica. No tiene ninguna equivalencia con ningún componente de UIKit.

Aquí podéis consultar la documentación oficial

Su inicialización se realiza de la siguiente forma:

EmptyView()

Este componente no tiene sentido usarlo en solitario, ya que va asociado a flujos concretos donde se requiere devolver un View, y nosotros no queremos mostrar ningún View. Vamos a ver algunos casos:

EmptyView y Toggle

Podemos devolver un EmptyView cuando creamos un Toggle. Esto hará que el Toggle no tenga ningún texto asociado y siga ocupando todo el ancho disponible.

Toggle(isOn: .constant(true)) {
    EmptyView()
}

EmptyView y NavigationLink

Permite tener un NavigationLink que no tiene representación gráfica, pero conserva su funcionalidad.

@State private var navigate = false

...

NavigationLink(destination: Text("New Screen"), isActive: $navigate) {
    EmptyView()
}

Por ejemplo, podemos usarlo en un List parar mantener la funcionalidad de navegar a una nueva pantalla al pulsar una celda.

struct ContentView: View {

    var body: some View {
        NavigationView {
            List {
                ForEach(0..<30) {
                    cell($0)
                }
            }
        }
    }
    
    func cell(_ index: Int) -> some View {
        HStack {
            Text("Empty: Go to index: (index)")
        }
        .overlay(
            NavigationLink(destination: Text("Index: (index)")) {
                EmptyView()
            }
        )
    }
}

EmptyView en funciones

Hay otras ocasiones donde creamos una función que devuelve some View, pero por algún caso interno hay ocasiones donde no se debe devolver nada. En estas situaciones también podemos usar EmptyView.

Por ejemplo, podemos crearnos una nueva función en View para poder imprimir un log por consola dentro de los ViewBuilder de SwiftUI.

extension View {
    func Print(_ vars: Any...) -> some View {
        for v in vars { print(v) }
        return EmptyView()
    }
}

También podemos crearnos una función (showSelectedFilms) que devuelva un some View en base a un parámetro de la misma. En caso de no contener datos, devuelve un EmptyView.

struct ContentView : View {
    @State var selection = Set()
    
    @State private var items = Film.mockFilms
    
    var body: some View {
        VStack(spacing: 15) {
            List(selection: $selection) {
                ForEach(items) {
                    Text($0.name)
                }
                
            }
            showSelectedFilms()
        }
        .navigationBarItems(trailing: EditButton())
        .navigationBarTitle("Multiple", displayMode: .inline)
        .navigationColor(background: UIColor(red: 31/255, green: 155/255, blue: 222/255, alpha: 1), title: .white)
    }
    
    func showSelectedFilms() -> some View {
        if !selection.isEmpty {
            let result = items.compactMap { (film) -> Film? in
                selection.contains(film.id) ? film : nil
            }.map {
                return $0.name
            }
            return AnyView(
                VStack(spacing: 5) {
                    Text("Your select:")
                        .font(.headline)
                    Text("(result.joined(separator: ", "))")
                        .font(.body)
                }
                .padding())
        } else {
            return AnyView(EmptyView())
        }
    }
    
    struct Film: Identifiable {
        let id: UUID = UUID()
        
        var name: String
        
        static let mockFilms = [Film(name: "Iron Man"),
                                Film(name: "The Incredible Hulk"),
                                Film(name: "Iron Man 2"),
                                Film(name: "Thor"),
                                Film(name: "Captain America: The First Avenger"),
                                Film(name: "Marvel's The Avengers")]
    }
}

Ejemplo

Puedes encontrar este ejemplo en github.com bajo el apartado EmptyView

Rafael Fernández,
iOS Tech Lider