Context
I have a generic SwiftUI view called ComponentRow
and would like to use it in different places inside my app. However, my model only returns the Component
as (any Component)?
, which is why I used a Switch
to bridge between any
and the generic ComponentRow
view (see variant A in code example).
I came with an idea to simplify the code (see variant B in code example), however, I get the following Compiler Error:
Adjacent operators are in non-associative precedence group 'ComparisonPrecedence'
Code
protocol Component {
static var name: String { get }
}
struct ContentView: View {
var body: some View {
// Variant A: Current Solution
switch component {
case let componentA as ComponentA: ComponentRow<ComponentA>()
case let componentB as ComponentB: ComponentRow<ComponentB>()
case let componentC as ComponentC: ComponentRow<ComponentC>()
default: EmptyView()
}
// Variant B: My Idea, does not work
if let safeComponent = component {
EventRow<type(of: safeComponent)>(for: profile, with: event)
}
}
var component: (any Component)? {
// Some Logic...
}
}
struct ComponentRow<C: Component>: View {
var body: some View {
Text(C.name)
}
}
Question
- Is there a way to avoid switching through all possible objects conforming to
Component
to initiate the appropriateComponentRow
?
CodePudding user response:
In order to use generics properly you need an instance of an object that conforms to the protocol Component
.
Here's a quick example of what I think you're trying to accomplish:
protocol Component {
var name: String { get set } // <~ Not static
}
struct FirstComponent: Component {
var name: String
}
struct SecondComponent: Component {
var name: String
}
struct ComponentRow<C: Component>: View {
let component: C
var body: some View {
Text(component.name)
}
}
struct ContentView: View {
let first = FirstComponent(name: "Foo") // <~ instance
let second = SecondComponent(name: "Bar") // <~ instance
var body: some View {
List {
ComponentRow(component: first)
ComponentRow(component: second)
}
}
}
Hope this helps!
CodePudding user response:
May be something like :
protocol Component { var name: String { get } }
struct ComponentA: Component {
var name: String = "A"
}
struct ComponentB: Component {
var name: String {
get {
return "B"
}
}
}
struct ContentView: View {
var body: some View {
// Variant B: My Idea, does not work
if let safeComponent = components {
ComponentRow(component: safeComponent)
} else {
EmptyView()
}
}
var components: (any Component)? {
// Some Logic...
return (ComponentB())
}
}
struct ComponentRow: View {
// You do not need to declare a generic type
var component: any Component
var body: some View {
Text(component.name)
}
}