如何在 SwiftUI 中向下转换协议上的 Binding<struct>?

问题描述 投票:0回答:1

我想访问仅在

label
协议中具有绑定的
ComponentWithLabel
 属性。但我无法向下转换
any Component
 在
any ComponentWithLabel
上的绑定并访问
label
属性。有什么解决办法吗?

protocol Component { 
    var identifier: String { get }
}

protocol ComponentWithLabel: Component {
    var label: String { get set }
}

struct NormalComponent: Component {
    let identifier: String = "Normal"
}

struct NormalComponentWithLabel: ComponentWithLabel {
    let identifier: String = "Normal"
    var label: String = "Label"
}

struct ContentView: View {
    @State var normalComponent: any Component = NormalComponent()
    @State var normalComponentWithLabel: any Component = NormalComponentWithLabel()
    var body: some View {
        VStack {
            ComponentRepresentingView(component: $normalComponent)
            ComponentRepresentingView(component: $normalComponentWithLabel)
        }
    }
}

struct ComponentRepresentingView: View {
    @Binding var component: any Component
    var body: some View {
        VStack {
            if component is ComponentWithLabel {
                TextField("Label", text: $component.label) // Value of type 'Binding<any Component>' has no dynamic member 'label' using key path from root
type 'any Component'
            }
            Text(component.identifier)
        }
    }
}

我已尝试使用此代码,但它不起作用。

ios swift swiftui protocols downcast
1个回答
0
投票

我会建议在sweeper的答案中使用init扩展 但对于你目前的情况,你可以这样做

struct ComponentRepresentingView: View {
    @Binding var component: any Component
    var body: some View {
        VStack {
            if component is ComponentWithLabel {
               let binding = Binding<ComponentWithLabel>.init(get: {
                    component as! ComponentWithLabel // Forcefully unwrapped we already checked in if condition 
                }, set: { label in
                    component = label
                })
                TextField("Foo", text: binding.label)

            }

            Text(component.identifier)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.