为什么Swift无法在ForEach循环中使用array [index + 1]渲染视图?

时间:2020-02-29 23:49:29

标签: ios swift swiftui

我收到与在SwiftUI的ForEach循环中使用提供的索引访问数组中的项目有关的错误。

我有一系列信息,这些信息用于将信息传递给用于渲染卡片的结构。每个HStack我需要两张这些卡,因此我遍历阵列并按如下方式调用这些卡:

ForEach(0..<array.count){item in
  Card(name: array[item].name)
  Card(name: array[item+1].name)
}

但这会引发错误:The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

我要完成的是在单个VStack中一堆水平堆栈,每个堆栈有2个项目。这样我有2张并排卡的列表。这似乎是蛮力地强行执行该行为的一种简单方法,但是我一直遇到错误。

我可能只是要切换到另一种样式的Hstack,该样式将在添加的每第3行中换行到下一行,但是我仍然想知道是否有人可以告诉我为什么会发生此错误。这似乎是一个简单操作,但编译器无法完成

这是我正在运行的实际代码,如果上面的示例没有剪切它。此代码最奇怪的是,它只会在 SECOND 项+1之后失败。如果我只在代码中执行一次,就可以运行它。

        ForEach(0..<self.decks.count){item in

             HStack(spacing: 30){
                if(item+1 < self.decks.count){
                    StudyCards(cardTitle: self.decks[item].deckTitle, cardAmt: self.decks[item].stackAmount, lastStdy: self.decks[item].lastStudied)

                    StudyCards(cardTitle: self.decks[item+1].deckTitle, cardAmt: self.decks[item+1].stackAmount, lastStdy: self.decks[item+1].lastStudied)
                }
                Spacer()
                    .padding(.bottom, 4)
             } else{
                    StudyCards(cardTitle: self.decks[item].deckTitle, cardAmt: self.decks[item].stackAmount, lastStdy: self.decks[item].lastStudied)
           }

            }
        }

2 个答案:

答案 0 :(得分:0)

正如您所说,我复制了您的错误,仅当您在ForEach中有多个“ item + 1”时才会发生此错误,

Text(self.array[item + 1] + " - " + self.array[item + 1])

因此,我认为问题与您的特定视图无关。一种解决方案是创建一个使item递增并返回视图的函数:

struct ContentView: View {
    @State var array: [String] = ["zero","one","two", "three"];

    var body: some View {
        VStack {
            ForEach(0..<array.count) { item in
                Text(self.array[item])
                if item + 1 < self.array.count {
                    self.makeView(item: item)
                }
            }

        }
    }

    func makeView(item: Int) -> Text {
        let nextItem = item + 1
        return Text(self.array[nextItem] + " - " + self.array[nextItem])
    }
}

live example

参考:swiftui-increment-variable-in-a-foreach-loop

答案 1 :(得分:0)

好的,我找到了解决方案!

我在这里使用了视图构建器的这种实现方式:(https://www.hackingwithswift.com/quick-start/swiftui/how-to-position-views-in-a-grid

struct GridStack<Content: View>: View {
    let rows: Int
    let columns: Int
    let content: (Int, Int) -> Content

    var body: some View {
        VStack(spacing: 30){
            ForEach(0 ..< rows, id: \.self) { row in
                HStack(spacing: 30){
                    ForEach(0 ..< self.columns, id: \.self) { column in
                        self.content(row, column)
                    }
                }
            }
        }
    }

    init(rows: Int, columns: Int, @ViewBuilder content: @escaping (Int, Int) -> Content) {
        self.rows = rows
        self.columns = columns
        self.content = content
    }
}

然后我像下面这样称呼它。我必须添加if语句,因为如果没有它,它将渲染一张额外的卡。现在,我已经成功实现了具有2列和任意行的网格!无需第三方库!

        GridStack(rows: self.rows, columns: 2){ row, col in
            if(row*2 + col < self.count){
                StudyCards(cardTitle: self.decks[row*2 + col].deckTitle, cardAmt: self.decks[row*2 + col].stackAmount, lastStdy: self.decks[row*2 + col].lastStudied)
            }