基于State Int的SwiftUI ForEach

18

我在我的视图中将一个整数值存储为状态。当我按下按钮时,这个整数增加一。当我打印出这个整数值时,它工作得很好。

现在我有一个ForEach循环,它基于这个整数进行迭代。当我默认设置我的状态为2时,它在开始时工作得很好。但是,当我增加这个整数时,我的ForEach不再被调用。

我理解State将重新加载我的实际视图。它只加载特定的部分吗?

这里是我声明我的State:

@State var s_countVenues   : Int = 2

这是我使用的 ForEach。一开始它能正常工作,但更改 s_countVenues 时不会更新视图。

ForEach(0..<self.s_countVenues)
{_ in
    HStack(spacing: 0)
    {
        //here comes my view
    }
}
如果需要,这里我将将我的值增加一。它有效,我打印了更改内容,如果我在标签中使用它,标签将会得到更新。

如果需要,这里我将将我的值增加一。它有效,我打印了更改内容,如果我在标签中使用它,标签将会得到更新。

self.s_countVenues += 1
TL:DR:
我的Int状态正在工作。我可以在标签中增加和打印它。然而,在ForEach语句中将其用作语句后,更改后不会再次调用该循环。
3个回答

52

来源:苹果文档

extension ForEach where Data == Range<Int>, ID == Int, Content : View {

    /// Creates an instance that computes views on demand over a *constant*
    /// range.
    ///
    /// This instance only reads the initial value of `data` and so it does not
    /// need to identify views across updates.
    ///
    /// To compute views on demand over a dynamic range use
    /// `ForEach(_:id:content:)`.
    public init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)
}

因此,您必须使用(如Apple所建议的)

struct ContentView: View {
    @State var counter = 0
    var body: some View {
        VStack {
            ForEach(0 ..< counter, id:\.self) { i in
                    Text("row: \(i.description)")
                }
            Button(action: {
                self.counter += 1
            }, label: {
                Text("counter \(counter.description)")
            })
        }
    }
}

@davidev Asperi的答案是可行的,但在你理解它的工作原理之前不要使用它。它会在计数器更改时重新创建ForEach,这可能是你意料之外的事情。 - user3441734
好的,谢谢。你的意思是它会再次循环整个ForEach吗?而你只是添加最新的与新id? - davidev
1
@davidev。大致上是这样的。没有任何循环,ForEach只是结构体,而不是描述循环的Swift表达式。 - user3441734
5
简而言之:使用 id: \.self - Tamás Sengel
@TamásSengel,如果我们使用id:\.self,当发生任何更改时,内容/视图不会更新。 - Harsha
@Harsha 我很确定那不是这种情况。 - Tamás Sengel

7

我使用 ', id: .self' 将其静音


2
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

7

这不是由于状态所致,而是因为您使用了带有常量RangeForEach构造函数,这是一项已记录的功能,因此不应更新,因此未被更新。最简单的解决方案是使用与您的状态连接的标识符。这只是为了让渲染引擎知道ForEach是新的,需要刷新(已在Xcode 11.2 / iOS 13.2中进行了测试)。

ForEach(0..<self.s_countVenues)
{_ in
    HStack(spacing: 0)
    {
        //here comes my view
    }
}.id(s_countVenues)

1
非常感谢您的帮助。它完美地运行了。简短而完美的答案。 - davidev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接