SwiftUI 在 ForEach 循环中获取下一个项目
SwiftUI get next item in ForEach loop
我正在尝试实现一个 VStack 网格,当 ForEach 循环中的下一个项目满足条件时,它需要一个 HStack。我有下面的代码显示数组中的项目,但我不知道如何获取下一个要检查的项目。
这是我目前的情况。
VStack {
ForEach(item.cards, id: \.self) { item in
switch item.card.size {
case .Large:
LargeCard(card: item.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: item.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: item.card, viewModel: CardViewModel())
// This is where I think I need to check and I tried somthing like below, but the compiler crashes
if [=10=] + 1 < item.cards.count {
if item.card.size == .Small {
SmallCard(card: item.card, viewModel: CardViewModel())
}
}
}
case .none:
Text("No more.")
}
}
}
这是项目结构:
struct Item: Decodable, Hashable {
let card: Card
}
这是我想要得到的。
您可以尝试将 id
添加到您的结构 Item
,例如:
struct Item: Identifiable, Decodable, Hashable {
let id = UUID()
let card: Card
}
然后使用:
VStack {
ForEach(item.cards, id: \.self) { theItem in
switch theItem.card.size {
case .Large:
LargeCard(card: theItem.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: theItem.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: theItem.card, viewModel: CardViewModel())
// here use the id to find the next item
if let ndx = item.cards.firstIndex(where: {[=11=].id == theItem.id}) {
if ndx + 1 < item.cards.count {
let nextItem = item.cards[ndx + 1]
if nextItem.card.size == .Small {
SmallCard(card: nextItem.card, viewModel: CardViewModel())
}
}
}
}
case .none:
Text("No more.")
}
}
}
您也可以使用评论中提到的枚举,例如:
VStack {
ForEach(Array(item.cards.enumerated()), id: \.offset) { index, theItem in
switch theItem.card.size {
case .Large:
LargeCard(card: theItem.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: theItem.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: theItem.card, viewModel: CardViewModel())
// here use the index to find the next item
if index + 1 < item.cards.count {
let nextItem = item.cards[index + 1]
if nextItem.card.size == .Small {
SmallCard(card: nextItem.card, viewModel: CardViewModel())
}
}
}
case .none:
Text("No more.")
}
}
}
请注意,您似乎应该使用 .environmentObject(viewModel)
通过
单个 CardViewModel()
到视图,而不是每次都创建一个新的 CardViewModel()
。
我正在尝试实现一个 VStack 网格,当 ForEach 循环中的下一个项目满足条件时,它需要一个 HStack。我有下面的代码显示数组中的项目,但我不知道如何获取下一个要检查的项目。
这是我目前的情况。
VStack {
ForEach(item.cards, id: \.self) { item in
switch item.card.size {
case .Large:
LargeCard(card: item.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: item.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: item.card, viewModel: CardViewModel())
// This is where I think I need to check and I tried somthing like below, but the compiler crashes
if [=10=] + 1 < item.cards.count {
if item.card.size == .Small {
SmallCard(card: item.card, viewModel: CardViewModel())
}
}
}
case .none:
Text("No more.")
}
}
}
这是项目结构:
struct Item: Decodable, Hashable {
let card: Card
}
这是我想要得到的。
您可以尝试将 id
添加到您的结构 Item
,例如:
struct Item: Identifiable, Decodable, Hashable {
let id = UUID()
let card: Card
}
然后使用:
VStack {
ForEach(item.cards, id: \.self) { theItem in
switch theItem.card.size {
case .Large:
LargeCard(card: theItem.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: theItem.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: theItem.card, viewModel: CardViewModel())
// here use the id to find the next item
if let ndx = item.cards.firstIndex(where: {[=11=].id == theItem.id}) {
if ndx + 1 < item.cards.count {
let nextItem = item.cards[ndx + 1]
if nextItem.card.size == .Small {
SmallCard(card: nextItem.card, viewModel: CardViewModel())
}
}
}
}
case .none:
Text("No more.")
}
}
}
您也可以使用评论中提到的枚举,例如:
VStack {
ForEach(Array(item.cards.enumerated()), id: \.offset) { index, theItem in
switch theItem.card.size {
case .Large:
LargeCard(card: theItem.card, viewModel: CardViewModel())
case .Medium:
MediumCard(card: theItem.card, viewModel: CardViewModel())
case .Small:
HStack(spacing: 16) {
SmallCard(card: theItem.card, viewModel: CardViewModel())
// here use the index to find the next item
if index + 1 < item.cards.count {
let nextItem = item.cards[index + 1]
if nextItem.card.size == .Small {
SmallCard(card: nextItem.card, viewModel: CardViewModel())
}
}
}
case .none:
Text("No more.")
}
}
}
请注意,您似乎应该使用 .environmentObject(viewModel)
通过
单个 CardViewModel()
到视图,而不是每次都创建一个新的 CardViewModel()
。