ForEach 嵌套在列表中 - 当行数达到特定点时停止生成行
ForEach nested in List - stop producing rows when row count hits particular point
我有一个包含嵌套 ForEach 循环的列表,应该 获取数据并在行计数器达到三时停止生成行,但我收到以下错误消息
Type '()' cannot conform to 'View
显示三行后是否可以切断循环?我的最终目标是在显示三行后显示“查看更多”按钮。
import SwiftUI
struct RecipeListView: View {
@State var listofRecipes: [RecipeListModel] = RecipeList.recipes
@State private var recipeCounter = 0
init(){
UITableView.appearance().backgroundColor = .clear
}
var body: some View {
VStack{
Text("Recipes")
.padding(.bottom, -20)
//.padding(.top, 40)
.font(.title2)
List{
ForEach(listofRecipes, id: \.id){ recipe in
recipeCounter += 1
if(recipeCounter < 3){
HStack{
Image(recipe.image)
.resizable()
.frame (width: 70, height:70)
.cornerRadius(15)
VStack{
Text(recipe.name)
.font(.title2)
//temp solution until I can center it
.padding(.trailing, 25)
NavigationLink(destination: {RecipeController(name: recipe.name, image: recipe.image)}, label: {
Text("View Recipe")
.padding(5)
.foregroundColor(.black)
.background(Color("completeGreen"))
.frame(maxWidth: .infinity)
.cornerRadius(14)
})
.padding(4)
}
}
}
}
}
}
}
}
您的类型不符合视图,因为您无法更改视图中的变量。您可以声明 let
、使用 if
或 switch
,但不能声明 var
或直接更改值 - 因此,不允许使用 recipeCounter += 1
.
一个解决方案是创建一个仅包含前 3 项的临时列表,然后在用户决定查看其余项后将其更改为完整列表。
下面的示例对代码的每个部分做了一些解释:
struct Example: View {
// The full list is a let constant
let fullList = [Recipe("First"),
Recipe("Second"),
Recipe("Third"),
Recipe("Fourth"),
Recipe("Fifth")]
// The list is a @State variable: .onAppear will set
// it to contain the first 3 items, then it'll change
// to the full list
@State private var listofRecipes = [Recipe]()
var body: some View {
VStack{
Text("Recipes")
.font(.title2)
.padding()
List{
ForEach(listofRecipes, id: \.id){ recipe in
Text(recipe.text)
}
}
// "Show more" button: will change the list
// to make it contain all the items
Button {
withAnimation {
listofRecipes = fullList
}
} label: {
Text("Show more")
}
}
// When the view appears, set the list to contain only the
// first 3 items
.onAppear {
// Handle case when the list contains only 3 elements or less
if fullList.count > 3 {
listofRecipes = fullList.dropLast(fullList.count - 3)
}
}
}
struct Recipe {
let id = UUID()
let text: String
init(_ text: String) {
self.text = text
}
}
}
如@HunterLion 所述,问题是由 recipeCounter += 1
.
引起的
解决此问题的另一种方法是在您的条件中直接使用列表索引:
ForEach(listofRecipes.indices) { index in
if(index < 3) {
HStack {
Image(listofRecipes[index].image)
....
另外两个人所说的替代方法是在 listofRecipes
上使用 .prefix 修饰符。这将 return 包含前 n 个元素的数组子序列。
ForEach(listofRecipes.prefix(3)) { recipe in
HStack {
...
我有一个包含嵌套 ForEach 循环的列表,应该 获取数据并在行计数器达到三时停止生成行,但我收到以下错误消息
Type '()' cannot conform to 'View
显示三行后是否可以切断循环?我的最终目标是在显示三行后显示“查看更多”按钮。
import SwiftUI
struct RecipeListView: View {
@State var listofRecipes: [RecipeListModel] = RecipeList.recipes
@State private var recipeCounter = 0
init(){
UITableView.appearance().backgroundColor = .clear
}
var body: some View {
VStack{
Text("Recipes")
.padding(.bottom, -20)
//.padding(.top, 40)
.font(.title2)
List{
ForEach(listofRecipes, id: \.id){ recipe in
recipeCounter += 1
if(recipeCounter < 3){
HStack{
Image(recipe.image)
.resizable()
.frame (width: 70, height:70)
.cornerRadius(15)
VStack{
Text(recipe.name)
.font(.title2)
//temp solution until I can center it
.padding(.trailing, 25)
NavigationLink(destination: {RecipeController(name: recipe.name, image: recipe.image)}, label: {
Text("View Recipe")
.padding(5)
.foregroundColor(.black)
.background(Color("completeGreen"))
.frame(maxWidth: .infinity)
.cornerRadius(14)
})
.padding(4)
}
}
}
}
}
}
}
}
您的类型不符合视图,因为您无法更改视图中的变量。您可以声明 let
、使用 if
或 switch
,但不能声明 var
或直接更改值 - 因此,不允许使用 recipeCounter += 1
.
一个解决方案是创建一个仅包含前 3 项的临时列表,然后在用户决定查看其余项后将其更改为完整列表。
下面的示例对代码的每个部分做了一些解释:
struct Example: View {
// The full list is a let constant
let fullList = [Recipe("First"),
Recipe("Second"),
Recipe("Third"),
Recipe("Fourth"),
Recipe("Fifth")]
// The list is a @State variable: .onAppear will set
// it to contain the first 3 items, then it'll change
// to the full list
@State private var listofRecipes = [Recipe]()
var body: some View {
VStack{
Text("Recipes")
.font(.title2)
.padding()
List{
ForEach(listofRecipes, id: \.id){ recipe in
Text(recipe.text)
}
}
// "Show more" button: will change the list
// to make it contain all the items
Button {
withAnimation {
listofRecipes = fullList
}
} label: {
Text("Show more")
}
}
// When the view appears, set the list to contain only the
// first 3 items
.onAppear {
// Handle case when the list contains only 3 elements or less
if fullList.count > 3 {
listofRecipes = fullList.dropLast(fullList.count - 3)
}
}
}
struct Recipe {
let id = UUID()
let text: String
init(_ text: String) {
self.text = text
}
}
}
如@HunterLion 所述,问题是由 recipeCounter += 1
.
解决此问题的另一种方法是在您的条件中直接使用列表索引:
ForEach(listofRecipes.indices) { index in
if(index < 3) {
HStack {
Image(listofRecipes[index].image)
....
另外两个人所说的替代方法是在 listofRecipes
上使用 .prefix 修饰符。这将 return 包含前 n 个元素的数组子序列。
ForEach(listofRecipes.prefix(3)) { recipe in
HStack {
...