#ios #swift #swiftui #protocols #identifiable
Вопрос:
У меня есть небольшой вопрос о соответствии Identifiable
SwiftUI
требованиям .
Бывают ситуации, когда от нас требуется, чтобы мы соответствовали заданному типу MyType Identifiable
.
Но я сталкиваюсь со случаем, когда от меня требуется, чтобы [MyType] (массив MyType) соответствовал Identifiable
.
У меня уже есть свой тип, соответствующий Identifiable
. Что я должен сделать, чтобы также соответствовать [MyType] Identifiable
?
Ответ №1:
Я предлагаю встроить [MyType]
в структуру, а затем привести структуру в соответствие Identifiable
. Что-то вроде этого:
struct MyType: Identifiable {
let id = UUID()
}
struct Container: Identifiable {
let id = UUID()
var myTypes = [MyType]()
}
Использование:
struct ContentView: View {
let containers = [
Container(myTypes: [
MyType(),
MyType()
]),
Container(myTypes: [
MyType(),
MyType(),
MyType()
])
]
var body: some View {
/// no need for `id: .self`
ForEach(containers) { container in
...
}
}
}
Ответ №2:
Вы можете написать расширение, чтобы соответствовать Array
Identifiable
.
Поскольку расширения не могут содержать сохраненные свойства, а также потому , что имеет смысл, чтобы два «одинаковых» массива также имели одно и то же id
, вам нужно будет вычислить их на id
основе содержимого массива.
Самый простой подход здесь заключается в том, можете ли вы соответствовать своему типу Hashable
:
extension MyType: Hashable {}
Это также позволяет [MyType]
соответствовать Hashable
, и поскольку id
может быть любым Hashable
, вы можете использовать сам массив как свой собственный id
:
extension Array: Identifiable where Element: Hashable {
public var id: Self { self }
}
Или, если хотите, id
это может быть Int
:
extension Array: Identifiable where Element: Hashable {
public var id: Int { self.hashValue }
}
Конечно, вы можете сделать это только для своего собственного типа where Element == MyType
, но этот тип должен быть public
таким .
Комментарии:
1. @New_Dev. Прежде чем увидеть этот ответ, я на самом деле попробовал его, основываясь на вашем предложении в комментарии, который вы ранее написали. Но я потерпел неудачу. С этой новой идеей использования хэширования это может сработать, но я должен сказать, что мне не очень нравится идея «использовать сам массив в качестве собственного идентификатора».
2. @Мишель. почему нет?
Identifiable
просто нужноHashable
… так что под прикрытием он просто использует хэш.3. @Michel, Если вам это неудобно, вы можете сделать
id
anInt
, используя значение хэша напрямую — см. Обновленный ответ4. ДА. Я думаю, это тоже может сработать. Еще один интересный момент вашего предложения, вы написали «потому что имеет смысл, чтобы два массива, которые являются»одинаковыми», также имели один и тот же идентификатор». Я не уверен, что именно так должен работать идентификатор. Идентификатор должен позволять вам различать n-й элемент и m-й элемент независимо от того, равны они или нет. Скажи мне, если я ошибаюсь.
5. @Michel — Я думаю, это зависит от того, чего вы хотите достичь и как вы хотите относиться к «равным» объектам. Это влияет на анимацию вставки и удаления в списке. Если вам нужно, чтобы каждый объект был уникальным, то вы используете что-то вроде
UUID
. Или вы можете использовать индекс объекта в массиве в качестве его идентификатора (но тогда объект не обязательно должен бытьIdentifiable
).