Oleksandr Matrosov
Oleksandr Matrosov

Reputation: 27123

SwiftUI build a list using enums

I am trying to create SwiftUI List based on enum strings. I am faced with this error:

Cannot invoke initializer for type 'List<_, _>' with an argument list of type '([HomeView.Data], @escaping (String) -> HomeMenuRow)'

enter image description here

I can't understand how to use id or how to iterate through enum to build a row.

Upvotes: 7

Views: 7936

Answers (3)

Chris
Chris

Reputation: 4391

A ForEach element needs a binding, so another option I tried is to use .constant within the ForEach. This does mean you might have to use item.wrappedValue to access properties.

ForEach(.constant(Whatever.allCases)) { item in
    Text(item.wrappedValue.rawValue)
}

Upvotes: 0

green_knight
green_knight

Reputation: 1385

You don't need Identifiable here. I've added selections as well, because why not:

enum Whatever: String, CaseIterable {
    case one
    case two
}

struct ContentView: View {
  @Binding var selection: Whatever?


    var body: some View {
        VStack {
            List (Whatever.allCases, id: \.rawValue, selection: $selection) { item in
                Text(item.rawValue)
.tag(item)
            }
        }
    }
}

Selection has to be optional (the error messages here are not overly helpful), but this is basically how you get a list that changes an enum value. You can also use this for type erasure to display sublists of different data types in a sidebar (eg books, magazines, videos): use an enum with associated data, group by enum case, and enjoy. It is not necessary for id to be a static property; if your case is one(content: Book) you can have a computed id property with a switch statement and case one(let book): return book.id, and simply use an id: .id key path. (Unless elsewhere in Swift 5, the return keyword he remains mandatory).

Upvotes: 3

Chris
Chris

Reputation: 8091

try this:

enum Whatever  : String, CaseIterable, Identifiable {

    var id : String { UUID().uuidString }

    case one = "one"
    case two = "two"
}

struct ContentView: View {
    var body: some View {
        VStack {
            List (Whatever.allCases) { value in
                Text(value.rawValue)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Upvotes: 17

Related Questions