0

I made a struct to represent a section in the UI.

 @Observable class Model {
       
        struct Section: Identifiable {
            var id: String {
                return title
            }
            let title: String
            let products: [String]
            let productViewStyle: any ProductViewStyle
        }

        let sections: [Section]
        
        init(sections: [Section]) {
            self.sections = sections
        }
    }

Each section has it's own productViewStyle which is a SwiftUI protocol with associatedtype. I can create the model:

    let test = InAppPurchase.Products.Model(sections: [InAppPurchase.Products.Model.Section(title: "test", products: ["testProdutID"], productViewStyle: .large)])

When I want to use it on the UI I got an error:

ProductView(id: test.sections.first!.products.first!)
            .productViewStyle(test.sections.first!.productViewStyle)

Type 'any ProductViewStyle' cannot conform to 'ProductViewStyle'

How can I solve this issue?

MetaImi
  • 274
  • 2
  • 13
  • And an extra: .productViewStyle(1 == 1 ? .large : .compact) also gives an error because of a mismatching type. How does SwiftUI work in this way? – MetaImi Aug 29 '23 at 21:11
  • 2
    I think you need to redesign this. Can you show a [mcve], including but not limited to the declaration of `ProductViewStyle`. – Sweeper Aug 30 '23 at 00:32

2 Answers2

0

From what I see, let productViewStyle: any ProductViewStyle requires anything that conforms to this protocol, not a concrete enum case. Assuming you have a specific property inside the enum which is required, you can use the following example

enum ProductView {
    case large
    case small
}

protocol ProductViewStyle {
    var productStyle: ProductView { get }
}

struct LargeProduct: ProductViewStyle {
    var productStyle: ProductView = .large
}

let section = Model.Section(title: "Hello", products: ["Product 1"], productViewStyle: LargeProduct())
print(section.productViewStyle.productStyle) // prints large

You can create any class or struct that conforms to ProductViewStyle and pass in as a reference

Abdul Waheed
  • 863
  • 8
  • 14
0

I ended up with the following solution:

  • Created my own enum in the model level
  • Added a view modifier to use that enum and apply the corresponding ProductViewStyle
struct BikeProductViewStyle: ViewModifier  {
    let style: InAppPurchase.Products.Model.Section.Style
    
    func body(content: Content) -> some View {
        
        switch style {
        case .large:
            content.productViewStyle(.large)
        case .normal:
            content.productViewStyle(.compact)
        }
    }
}

Not the best solution, as in the model I wanted to store UI related values.

MetaImi
  • 274
  • 2
  • 13