ios - SwiftUI ForEach 未在 ScrollView 中正确更新

标签 ios swiftui

我有一个 SwiftUI ScrollView,里面有一个 HStack 和一个 ForEach。 ForEach 是基于 ObservableObject 的 Published 变量构建的,因此随着项目的添加/删除/设置,它会在 View 中自动更新。但是,我遇到了多个问题:

  1. 如果数组一开始是空的,然后添加了项目,则不会显示它们。
  2. 如果数组中有一些项目,我可以添加一个项目,它会显示,但添加更多不会。

如果我只有一个带 ForEach 的 HStack,则不会出现上述任何问题。一旦它在 ScrollView 中,我就会遇到问题。

下面是可以粘贴到 Xcode SwiftUI Playground 中以演示问题的代码。在底部,您可以取消注释/注释不同的行以查看两个不同的问题。

如果您取消注释问题 1,然后单击任一按钮,您将只看到 HStack 更新,而不是 ScrollView 中的 HStack 即使您看到这些项目的初始化打印语句。

如果您取消对问题 2 的注释,然后单击任一按钮,您应该会看到在单击一秒钟后 ScrollView 会更新,但如果您继续单击它不会更新 - 即使只有 HStack 会继续更新并初始化打印语句是 ScrollView 项目的输出。

import SwiftUI
import PlaygroundSupport
import Combine

final class Testing: ObservableObject {
    @Published var items: [String] = []

    init() {}

    init(items: [String]) {
        self.items = items
    }
}

struct SVItem: View {
    var value: String

    init(value: String) {
        print("init SVItem: \(value)")
        self.value = value
    }

    var body: some View {
        Text(value)
    }
}

struct HSItem: View {
    var value: String

    init(value: String) {
        print("init HSItem: \(value)")
        self.value = value
    }

    var body: some View {
        Text(value)
    }
}

public struct PlaygroundRootView: View {
    @EnvironmentObject var testing: Testing

    public init() {}

    public var body: some View {
        VStack{
            Text("ScrollView")
            ScrollView(.horizontal) {
                HStack() {
                    ForEach(self.testing.items, id: \.self) { value in
                        SVItem(value: value)
                    }
                }
                .background(Color.red)
            }
            .frame(height: 50)
            .background(Color.blue)
            Spacer()
            Text("HStack")
            HStack {
                ForEach(self.testing.items, id: \.self) { value in
                    HSItem(value: value)
                }
            }
            .frame(height: 30)
            .background(Color.red)
            Spacer()
            Button(action: {
                print("APPEND button")
                self.testing.items.append("A")
            }, label: { Text("APPEND ITEM") })
            Spacer()
            Button(action: {
                print("SET button")
                self.testing.items = ["A", "B", "C"]
            }, label: { Text("SET ITEMS") })
            Spacer()
        }
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = UIHostingController(
    // problem 1
    rootView: PlaygroundRootView().environmentObject(Testing())

    // problem 2
    // rootView: PlaygroundRootView().environmentObject(Testing(items: ["1", "2", "3"]))
)

这是一个错误吗?我错过了什么吗?我是 iOS 开发的新手。我确实尝试将实际项目设置/附加包装在 DispatchQueue.main.async 中,但这没有做任何事情。

此外,可能无关紧要,但如果您点击按钮的次数过多,应用程序似乎会崩溃。

最佳答案

刚遇到同样的问题。解决了空数组检查和不可见的 HStack

ScrollView(showsIndicators: false) {
    ForEach(self.items, id: \.self) { _ in
        RowItem()
    }

    if (self.items.count == 0) {
        HStack{
            Spacer()
        }
    }
}

关于ios - SwiftUI ForEach 未在 ScrollView 中正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59316078/

相关文章:

ios - 如何使用 NSUserDefaults 在 Swift 中存储自定义类数组?

带有presentModalViewController的ios uidatepicker

swift - 如何从 WatchOS 中的 SwiftUI 列表中删除分隔符?

swiftui - 当Live Activity更新数据时,图片会淡入淡出,如何关闭这个动画效果?

ios - 如何删除导航栏移动 Jquery 中的行分隔符

ios - UITableView 在模拟器 iOS 7.0 中正确呈现,但不适用于 iOS 6.1

iphone - 如何在代码中而不是 Interface Builder 中设置 didEndOnExit?

macos - 如何在 macOS SwiftUI 中创建默认按钮?

ios - 如何在 Swift 中使图像与其旁边的文本具有相同的高度?

ios - WidgetKit自定义Intent参数选择