I'm trying to create a Set of cards. Each card has an object assigned, that is then shown with a different colour and appears in different numbers on each card.
The issue appears when trying to work with the "Shape" Type associated with my individual Cards. The error message reads:
"Value of protocol type 'Shape' cannot conform to 'View'; only struct/enum/class types can conform to protocols"
import Foundation
import SwiftUI
var setCardSet: Array<SetCard> = [ ]
var counter: Int = 0
func createSet() -> Array<SetCard> {
for object in 0..<3 {
var chosenShape = objectLibrary[object]
for numberOfShapes in 0..<3 {
counter += 1
setCardSet.append(SetCard(id: counter, shape: chosenShape, numberOfShapes: numberOfShapes))
}
}
return setCardSet
}
struct SetCard: Identifiable {
var id: Int
var shape: Shape
var numberOfShapes: Int
}
var possibleSetCardShapes = [Diamond(), Tube(), Tube()] **as** [ **Any** ]
struct GameObject {
var name: String
var object: Shape
}
let objectLibrary = [Diamond(), Tube(), Swirl()]
At a later step, the individual objects are shown and "stacked" on the same card:
struct CardView: View {
var card: SetCard
var body: some View {
ZStack {
VStack{
ForEach(0 ..< card.numberOfShapes+1) {_ in
card.shape
}
}
}
}
}
In CardView you try to create a VStack of the card's shape property. For this to work, card.shape needs to be a type that conforms to the View protocol. In your code, card.shape conforms to the Shape type.
It looks like Shape is a protocol. So can you just get Shape to conform to View to fix this? Unfortunately it's not that simple. The definition of the View protocol looks like this:
public protocol View {
associatedtype Body : View
@ViewBuilder var body: Self.Body { get }
}
In particular, it has an assocciatedtype. That means you can't write something like this:
struct SetCard: Identifiable {
var id: Int
var shape: Shape // Error
var numberOfShapes: Int
}
The problem is that when we make a SetCard we'd have no way of knowing what the associated Body type is of the shape, which the compiler needs to know.
I think your best solution (though there are others) is to make the shapes an existing type that conforms to View. For example, what about Image? You could have
struct SetCard: Identifiable {
var id: Int
var shape: Image
var numberOfShapes: Int
}
let diamond = Image(systemName: "suit.diamond")
let card = SetCard(id: 1, shape: diamond, numberOfShapes: 3)