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、使用 ifswitch,但不能声明 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 {
         ...