简体   繁体   English

类型任何协议不能符合协议

[英]Type any Protocol cannot conform to Protocol

I am facing an issue when trying to initialize a view in SwiftUI. Let me explain:我在尝试初始化 SwiftUI 中的视图时遇到问题。让我解释一下:

I have a view called ExternalView, this view has a constraint with a protocol called ToggleableProtocol, then, this view internally consumes a view called InternalView, which is a view that has a constraint to a Hashable protocol.我有一个名为 ExternalView 的视图,该视图具有一个名为 ToggleableProtocol 的协议的约束,然后,该视图在内部使用一个名为 InternalView 的视图,该视图具有对 Hashable 协议的约束。

The error occurs when I try to create an instance of ExternalView and pass it an array of different structs that conform to the ToggleableItem protocol.当我尝试创建 ExternalView 的实例并将符合 ToggleableItem 协议的不同结构数组传递给它时,会发生错误。 The error says Type 'any TogleableItem' cannot conform to 'TogleableItem'错误提示Type 'any TogleableItem' cannot conform to 'TogleableItem'

TogleableItem可切换项目

public protocol TogleableItem: Hashable {
    var text: String { get }
    var isSelected: Bool { get set }
}

Structs conforming to the TogleableItem符合 TogleableItem 的结构

struct FirstObject: TogleableItem {
    var text = "FirstItem"
    var isSelected = false
}

struct SecondObject: TogleableItem {
    var text = "SecondItem"
    var isSelected = false
}

ContentView内容视图

struct ContentView: View {
    @State private var items: [any TogleableItem] = [
        FirstObject(),
        SecondObject()
    ]
    
    var body: some View {
        ExternalView(
            items: items
        ) { isSelected, index, _ in
            items[index].isSelected = isSelected
        }
    }
}

ExternalView外部视图

public struct ExternalView<T: TogleableItem>: View {
    private let items: [T]
    private let onItemTap: (Bool, Int, T) -> Void
    
    public init(
        items: [T],
        onItemTap: @escaping (Bool, Int, T) -> Void
    ) {
        self.items = items
        self.onItemTap = onItemTap
    }
    
    public var body: some View {
        InternalView(
            items: items
        ) { index, element in
            Text(element.text)
                .foregroundColor(element.isSelected ? .red : .blue)
        }
    }
}

InternalView内部视图

struct InternalView<Element: Hashable, Content: View>: View {
    private let items: [Element]
    private let content: (Int, Element) -> Content
    
    init(
        items: [Element],
        content: @escaping (Int, Element) -> Content
    ) {
        self.items = items
        self.content = content
    }
    
    var body: some View {
        LazyHStack(spacing: 0) {
            ForEach(items.indices, id: \.self) { index in
                content(index, items[index])
            }
        }
    }
}

Error错误

Thanks!!谢谢!!

I have tried changing the items parameter, inside the ExternalView to something like [any TogleableItem] but in the end it causes a similar error when consuming the InternalView我尝试将 ExternalView 内的 items 参数更改为 [any TogleableItem] 之类的内容,但最终在使用 InternalView 时会导致类似的错误

The problem with your code is that you define for instance ExternalView as generic您的代码的问题是您将例如ExternalView定义为通用

ExternalView<T: TogleableItem>

then you say that T can be of a (read one) type that conforms to TogleableItem but you want to use the view for a mix of types that conforms to TogleableItem .然后你说T可以是符合TogleableItem的(读取一个)类型,但你想将视图用于符合TogleableItem的混合类型。

The solution as I see it is to not make the view types generics and instead use TogleableItem directly in the declarations (I have skipped a lot of code below for brevity)我看到的解决方案是创建视图类型 generics 而是直接在声明中使用TogleableItem (为简洁起见,我在下面跳过了很多代码)

public struct ExternalView: View {
    private let items: [any TogleableItem]
    private let onItemTap: (Bool, Int, any TogleableItem) -> Void
    ...
}

struct InternalView<Content: View>: View {
    private let items: [any TogleableItem]
    private let content: (Int, any TogleableItem) -> Content
    ...
}

Another way to solve it if InternalView should be able to use other types than those conforming to TogleableItem is to use the original solution but without Element conforming to Hashable如果 InternalView 应该能够使用其他类型而不是符合TogleableItem的类型,则另一种解决方法是使用原始解决方案但不使用符合HashableElement

struct InternalView<Element, Content: View>: View {
    private let items: [Element]
    private let content: (Int, Element) -> Content

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 类型“任何视图”不能符合具有泛型的协议上的“视图” - Type 'any View' cannot conform to 'View' on protocol with generics 协议类型“Any”的值不能符合“Equatable”Swift - Value of protocol type 'Any' cannot conform to 'Equatable' Swift 类型“Any”不符合协议“Sequence” - Type 'Any' doesn't conform to protocol 'Sequence' “Type&#39;Program&#39;不符合&#39;任何对象&#39;协议” - “Type'Program' does not conform to protocol 'Any Object'” 协议类型“Any”的值不能符合“Equatable”; 只有结构/枚举/类类型可以符合协议 - Value of protocol type 'Any' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols 协议类型“名称”的值不能符合具有通用 function 的协议“名称” - Value of Protocol type 'name' cannot conform to protocol 'name' with generic function 类型不符合协议 - Type does not conform to protocol 类型()不符合协议 - Type () does not conform to protocol 协议类型不能符合协议,因为只有具体类型才能符合协议 - Protocol type cannot conform to protocol because only concrete types can conform to protocols swift 将字典转换为 jsonString 错误:协议类型 'Any' 不能符合 'Encodable' 因为只有具体类型才能符合协议 - swift Convert dictionary to jsonString error : Protocol type 'Any' cannot conform to 'Encodable' because only concrete types can conform to protocols
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM