-1

[Solved by making in an in between type]

struct ColorType: Identifiable {
        
    var id = UUID()
    var color: Color
}

End of edit

I have an array with custom SwiftUI Colors which reside in the assets folder. Within a View a Foreach itterates through these values like this:

let colors: [Color] = [Color("InstrumentColor100"),Color("InstrumentColor100"),Color("InstrumentColor101")]

ForEach( colors, id: \.self) { color in
    Rectangle().fill(color)
}

This will serve me the runtime error: ForEach<Array, Color, _ShapeView<Rectangle, Color>>: the ID NamedColor(name: "InstrumentColor100", bundle: nil) occurs multiple times within the collection, this will give undefined results!

I do understant this is due to id: .self not finding unique values to create unique ID's. I found this answer stating to use id: \.keyPath but I do not have a keyPath rendering 3 aditional errors.

What would be a low overhead way to make these values (apear) unique?

BTW, the code works, but the console overflows wthe the sayd error.

2
  • 1
    Do you actually need to display the duplicate colors? If not, you could simply remove the duplicates by using a Set. Commented Oct 24, 2022 at 12:05
  • It's drawing in layers on the ZStack, in some combinations double names are possible. @Raja Kishan Not completely. The ideau to create a sctruct with id and string does not wotk with Color() which needs an initialiser value, which String doesn't Commented Oct 24, 2022 at 12:56

2 Answers 2

4

you could try this simple approach:

ForEach(colors.indices, id: \.self) { index in  
       Rectangle().fill(colors[index]) 
} 
Sign up to request clarification or add additional context in comments.

3 Comments

I ended up not using .enumerated but creating an in between type with ID. like this: import Foundation import SwiftUI struct ColorType: Identifiable { var id = UUID() var color: Color }
does my answer not work for you? No need for any mumbo jumbo.
Sorry, I added a comment to the wrong answer. I got it working before I read your answer
1

One solution you can try is to derive an array with indices like this:

let foo = ["a", "b", "c"]
let bar = Array(foo.enumerated())
print(bar)
// [(offset: 0, element: "a"), (offset: 1, element: "b"), (offset: 2, element: "c")]

You now have an array with named tuples. Then you should be able to do:

ForEach(bar, \.offset) {
    tuple in
    Rectangle().fill(tuple.element)
}

2 Comments

This loook like a good solution. It seems it's still missing an argument label. When I run let colorsArray = Array(colors.enumerated()) ForEach( colorsArray, \.offset) { tupple in Rectangle().fill(tupple.element) } I get te error "Missing argument label 'id:' in call" on line with ForEach on it
Good to read this against use of .enumerated

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.