[英]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])
}
}
}
}
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
的类型,则另一种解决方法是使用原始解决方案但不使用符合Hashable
的Element
struct InternalView<Element, Content: View>: View {
private let items: [Element]
private let content: (Int, Element) -> Content
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.