Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 8, 2021 02:15 pm GMT

Empty List placeholder. SwiftUI

Year twenty twenty-one. Almost a month has passed since the WWDC. As usual Apple presented many amazing features/updates . As expected updated SwiftUI framework. But did not add placeholder for List view . It's not big deal, but it was one of my expectations from conference. Okay let's do it ourselves

The List is one of the most used view in apps.
When using the List, devs also must handle the state of an empty data range and show a placeholder.

As an example, consider a simple list of countries. Show placeholder when data is empty.

Countries

Placeholder

Country model:

struct Country: Identifiable {    let id = UUID()    let name: String}

So, have any ideas on how to implement a placeholder?

First idea If else

The first thing that comes to mind it's if else conditional statement.

struct ContentView: View {    @State var countries: [Country] = [] // Data source    var body: some View {        if countries.isEmpty {            Text("No Countries") // Placeholder                .font(.largeTitle)        } else {            List(countries) { country in // List countires                Text(country.name)                    .font(.title)            }        }    }}

Advantages:

  • the most simple and clear way
  • easy to modify
  • it works and shows the placeholder when needed
  • easy to use any view for placeholder

Disadvantages:

  • the code looks cumbersome
  • not reusable

It works and sometimes it's enough. But in production, it would be nice to have a component that implements the logic of displaying a placeholder inside the component. So, goes to the next idea.

Second idea EmptyList

Improve if else idea and move logic show/hide placeholder to custom view, call it EmptyList:

struct EmptyList<Items: RandomAccessCollection, ListRowView: View, PlaceholderView: View>: View where Items.Element: Identifiable {    private let items: Items    private let listRowView: (Items.Element) -> ListRowView    private let placeholderView: () -> PlaceholderView    /// - Parameters:    ///   - items: Source data for List. Item must implement Identifiable protocol    ///   - listRowView: View displayed for each source Item    ///   - placeholderView: Placeholder. View displayed when the items collection isEmpty    init(_ items: Items,         @ViewBuilder listRowView: @escaping (Items.Element) -> ListRowView,         @ViewBuilder placeholderView: @escaping () -> PlaceholderView) {        self.items = items        self.listRowView = listRowView        self.placeholderView = placeholderView    }    var body: some View {        if !items.isEmpty {            List { // List countires                ForEach(items) { item in                    self.listRowView(item)                }            }        } else {            placeholderView()        }    }}

Using the EmptyList is very easy. First parameter - data source, second parameter - list row view, and finally third parameter - placeholder view.

struct ContentView: View {    @State var countries: [Country] = [] // Data source    var body: some View {        EmptyList(countries, // Data items         listRowView: { country in // List row view            Text(country.name)                .font(.title)        }, placeholderView: {            Text("No Countries") // Placeholder                .font(.largeTitle)        })    }}

Advantages:

  • code looks clean and clear
  • easy to modify custom view
  • reusable in project
  • use any view for placeholder

Disadvantages:

  • list is embedded in EmptyList view, and if want to add some ViewModifier-s to the list, need for more efforts and modify code

Usually, I would have to say that this is all and say goodbye but is not all . I want to share an idea of how I cook placeholder for lists in my projects.

Preferred idea ViewModifier

Create custom ViewModifier to manage placeholder, call it EmptyDataModifier:

struct EmptyDataModifier<Placeholder: View>: ViewModifier {    let items: [Any]    let placeholder: Placeholder    @ViewBuilder    func body(content: Content) -> some View {        if !items.isEmpty {            content        } else {            placeholder        }    }}

Uses EmptyDataModifier:

struct ContentView: View {    @State var countries: [Country] = [] // Data source    var body: some View {        List(countries) { country in            Text(country.name)                .font(.title)        }        .modifier(EmptyDataModifier(            items: countries,            placeholder: Text("No Countries").font(.title)) // Placeholder        )     }}

That's it! Also via extension can little bit improve the solution and limited apply EmptyDataModifier only for List.

extension List {    func emptyListPlaceholder(_ items: [Any], _ placeholder: AnyView) -> some View {        modifier(EmptyDataModifier(items: items, placeholder: placeholder))    }}
struct ContentView: View {    @State var countries: [Country] = [] // Data source    var body: some View {        List(countries) { country in            Text(country.name)                .font(.title)        }        .emptyListPlaceholder(            countries,            AnyView(ListPlaceholderView()) // Placeholder         )    }}

Advantages:

  • code look clean and clear
  • no need to create a custom List view
  • easy to modify
  • reusable in project
  • use any view for placeholder
  • this way for can be used for any view placeholder

Disadvantages:

  • no (subjective opinion)

Instead of summary

In my opinion, the most suitable way to implement a placeholder is to use a custom ViewModifier.
I'm sure sooner or later the Apple will add a placeholder for the List view. Maybe this article will be as a request for this feature for Apple. Who knows.

Source code

Thanks for reading! See you soon.


Original Link: https://dev.to/toni777772/empty-list-placeholder-swiftui-4b7e

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To