JDev
JDev

Reputation: 5558

Why can't one iterate through enum data within a SwiftUI view?

Say I have some enum, Channel, filled with sample property data:

enum Channel: CaseIterable {
  case abc
  case efg
  case hij
  
  var name: String {
    switch self {
    case .abc:  return "ABC"
    case .efg:  return "EFG"
    case .hij:  return "HIJ"
    }
  }
}

extension Channel: Identifiable {
  var id: Self { self }
}

And some view implementation to fill said content with:

struct ChannelHome: View {
  var body: some View {
    VStack {
      ForEach(Channel.allCases) { channel in
        NavigationLink(destination: ChannelDetail(channel)) {
          Text(channel.name)
        }
      }
    }
  }
}   // big closure yikes

Why doesn't this work? Is this due to the nature of enums not having static properties and SwiftUI being declarative? Are there ways around this? Such as:

struct ChannelData {
  static let channels: [Channel] = [.abc, .efg, .hij]
  // or
  static func getChannels() -> [Channel] {
    var channelArray: [Channel]
    for channel in Channel.allCases {
      channelArray.append(channel)
    }
    return channelArray
  }
}

Or, more preferably, are there better practices for presenting small data sets like these in a SwiftUI view? I like being able to implement a visual UI of my properties for when I'm debugging, as a whole, at runtime (closer to the production stage).

I apologies in advance for the question, I am just getting into it with SwiftUI.

Upvotes: 23

Views: 17843

Answers (2)

swiftPunk
swiftPunk

Reputation: 1

Here are 2 simple ways for you, but not sure where can be helpful for you because with enum you cannot update ForEach elements, but it has a use case for showing data!

First way without any Identifiable id:

struct ContentView: View {        
    var body: some View {            
        ForEach(TestEnum.allCases, id: \.rawValue) { item in                 
            Text(item.rawValue)                
        }
    }        
}

enum TestEnum: String, CaseIterable { case a, b, c }

with Identifiable id that conforms to Identifiable protocol, you can cut , id: \.id even:

struct ContentView: View {
    var body: some View {
        ForEach(TestEnum.allCases, id: \.id) { item in
            Text(item.rawValue)
        }
    }
}

enum TestEnum: String, CaseIterable, Identifiable { case a, b, c
    var id: String { return self.rawValue }
}

Upvotes: 31

JDev
JDev

Reputation: 5558

Either Xcode was getting hung up on cache errors or I am a fool (probably the latter). Regardless, the issue seems to have been resolved with the following Identifiable extension to your enum, as well as a good ol' derived data purge and clean:

extension Channel: Identifiable {
  var id: Self { self }
}

I seem to have confused this issue with another long-time issue that I've constantly run into; mostly regarding enums and their distaste for storing static data (as is simply just the nature of their fast and lite structure).

Upvotes: 10

Related Questions