Handle programmatically adding Divider() inside ForEach loop

177 Views Asked by At

I am looking at ways to improve adding a Divider() in a SwiftUI view programmatically. The example code here does what I want visually, but I am thinking there should be a better way. The goal of what I want is to have a divider between each row in the VStack, and no Divider() at the top or bottom of the VStack. It seems wrong to duplicate the code in the if/else statements, except for the Divider(). enter image description here

struct ContentView: View {
    
    fileprivate struct Detail: Identifiable, Equatable {
        let name: String
        let image: String
        var id: String { name }
    }
    
    private let details: [Detail] = [
        Detail(name: "arrow", image: "arrow.clockwise"),
        Detail(name: "car", image: "car"),
        Detail(name: "clipboard", image: "doc.on.clipboard")
    ]
    
    var body: some View {
        NavigationView {
            VStack(alignment: .leading, spacing: 24) {
                ForEach(details, id: \.name) { detail in
                    if detail == details.last {
                        NavigationLink {
                            EmptyView()
                        } label: {
                            ContentLabelHelpView(name: detail.name, image: detail.image)
                        }
                    } else {
                        NavigationLink {
                            EmptyView()
                        } label: {
                            ContentLabelHelpView(name: detail.name, image: detail.image)
                        }
                        Divider()
                    }
                }
            }
            .padding()
        }
    }
}

fileprivate struct ContentLabelHelpView: View {
    let name: String
    let image: String
    
    var body: some View {
        VStack(alignment: .leading) {
            HStack(alignment: .firstTextBaseline) {
                Image(systemName: image)
                Text(name)
                Spacer()
                Image(systemName: "chevron.forward")
            }
        }
    }
}
1

There are 1 best solutions below

0
sumida On

Use the if on the Divider() to avoid code duplication:

var body: some View {
    NavigationView {
        VStack(alignment: .leading, spacing: 24) {
            ForEach(details, id: \.name) { detail in
                NavigationLink {
                    EmptyView()
                } label: {
                    ContentLabelHelpView(name: detail.name, image: detail.image)
                }
                if detail != details.last {
                    Divider()
                }
            }
        }
        .padding()
    }