#swift #swiftui #swift-protocols
#быстрый #свифтуи #swift-протоколы
Вопрос:
Надеюсь, у вас у всех были замечательные каникулы. С новым годом!
Итак, я использую протоколы как тип:
protocol Protocol_A_Or_B { }
protocol ProtocolA: Protocol_A_Or_B, Identifiable, Hashable, CaseIterable { }
protocol ProtocolB: Protocol_A_Or_B, Identifiable, Hashable, CaseIterable { }
Я удалил все переменные и функции из протоколов, поскольку считаю, что они не имеют отношения к проблеме, с которой я сталкиваюсь.
Я создал пару перечислений, которые реализуют либо ProtocolA
или ProtocolB
. Кроме того, у меня есть «основное перечисление», в котором есть метод, который возвращает массив объектов, который либо реализует ProtocolA
, либо ProtocolB
, для этого, ProtocolA
и ProtocolB
имеет «родительский» протокол ( Protocol_A_Or_B
).
enum MainEnum_: Int, Identifiable, Hashable, CaseIterable {
case One
case Two
case Three
case Four
case Five
var id:Int { rawValue }
var aOrBEnumArray: [Protocol_A_Or_B] {
switch self {
case .One:
return EnumTypeA.allCases
case .Two:
return EnumTypeB.allCases
default:
return []
}
}
}
enum EnumTypeA: Int, ProtocolA {
case Option1
case Option2
case Option3
var id:Int { rawValue }
}
enum EnumTypeB: Int, ProtocolB {
case OptionA
case OptionB
case OptionC
var id:Int { rawValue }
}
Пока все хорошо. Но когда я пытаюсь отправить массив объектов, которые реализуют Protocol_A_Or_B
, я получаю следующие ошибки:
Value of protocol type 'Protocol_A_Or_B' cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols
Value of protocol type 'Protocol_A_Or_B' cannot conform to 'Identifiable'; only struct/enum/class types can conform to protocols
Вот макет того View
, где я использую объекты. Я получаю ошибки в строках кода TheContentView2(data: arrayEnumTypeA)
и TheContentView2(data: arrayEnumTypeB)
.
struct EnumProtocolsTest: View {
var arrayEnumTypeA: [Protocol_A_Or_B] = MainEnum_.One.aOrBEnumArray
var arrayEnumTypeB: [Protocol_A_Or_B] = MainEnum_.Two.aOrBEnumArray
var body: some View {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
TheContentView2(data: MainEnum_.allCases) { item in
Text("(item.name)")
.padding()
.background(Color.purple)
}
}
}
ScrollView(.horizontal, showsIndicators: false) {
HStack {
TheContentView2(data: arrayEnumTypeA) { item in
Text("(item.id)")
.padding()
.background(Color.purple)
}
}
}
ScrollView(.horizontal, showsIndicators: false) {
HStack {
TheContentView2(data: arrayEnumTypeB) { item in
Text("(item.id)")
.padding()
.background(Color.purple)
}
}
}
}
}
}
Итак, насколько я понимаю, я думаю, что ошибка связана с пользовательским представлением, которое у меня есть ( TheContentView2
) , поскольку оно должно получать массив объектов, который реализует Identifiable
и Hashable
.
struct TheContentView2<Data: RandomAccessCollection, ElementView: View>: View where Data.Element: Identifiable, Data.Element: Hashable {
var data: Data
var itemView: (Data.Element) -> ElementView
var body: some View {
ForEach(data) { item in
itemView(item)
.padding()
.background(Color.purple)
}
}
}
Я не могу добавить свои протоколы как часть определения / подписи этого представления, но если это неверно, я могу запросить изменение.
Надеюсь, вы сможете мне помочь. Я не знаю, как я могу отправить массив объектов, которые реализуют родительский протокол ( Protocol_A_Or_B
). Не уверен, чего мне не хватает в определении протокола или в подписи пользовательского представления.
Спасибо!!!
Комментарии:
1. Похоже
Protocol_A_Or_B
, у него естьid
свойство? Это единственное, что общего междуProtocolA
иProtocolB
?2. Ошибки кажутся очевидными, вы не включили свой код протокола, но удалили наследование для Hashable и Identified из protocol_a_a_or_b . Вы можете включить переменную is, но не наследование.
3. @Sweeper, как упоминалось выше: я удалил все переменные и функции из протоколов, поскольку считаю, что они не имеют отношения к проблеме, с которой я сталкиваюсь. У Protocol_A_or_B есть свойство id, которое реализовано в перечислениях.
4. @loremipsum, если я добавлю наследование для идентифицируемого и хэшируемого в Protocol_A_Or_B, как вы упомянули, я получаю больше ошибок: «Protocol_A_Or_B может использоваться только как общее ограничение, поскольку оно имеет собственные или связанные требования к типу». Попробуйте.
5. @aнгел, ошибка на самом деле довольно описательная.
ForEach
(и из-за этогоTheContentView2
) требует соответствияIdentifiable
иProtocol_A_Or_B
не соответствует ему (протоколы могут наследоваться только от протоколов, они не соответствуют протоколам). Таким образом, вы не можете[Protocol_A_Or_B]
использовать массив таким образом. Если вам все еще требуются разные типы в одном массиве, прочитайте «удаление типа»