我有一个 SwiftUI ScrollView,里面有一个 HStack 和一个 ForEach。ForEach 是基于 ObservableObject 的 Published 变量构建的,因此当添加/删除/设置项目时,它将在视图中自动更新。但是,我遇到了多个问题:
如果我只有一个带有 ForEach 的 HStack,则上述问题都不会发生。一旦它在 ScrollView 中,我就会遇到问题。
下面是可以粘贴到 Xcode SwiftUI Playground 中以演示问题的代码。在底部,您可以取消注释/注释不同的行以查看两个不同的问题。
如果您取消注释问题 1,然后单击任一按钮,您将只看到 HStack 更新,而不会看到ScrollView 中的 HStack,即使您看到这些项目的 init 打印语句。
如果您取消注释问题 2,然后单击其中一个按钮,您应该会在第二次单击后看到 ScrollView 更新,但如果您继续单击它不会更新 - 即使只是 HStack 将继续更新并输出 init 打印语句对于 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"]))
)
Run Code Online (Sandbox Code Playgroud)
这是一个错误吗?我错过了什么吗?我是 iOS 开发的新手。我确实尝试在 DispatchQueue.main.async 中包装实际项目设置/附加,但这没有做任何事情。
此外,也许不相关,但如果您点击按钮足够多,应用程序似乎会崩溃。
刚刚遇到了同样的问题。通过空数组检查和不可见的 HStack 解决
ScrollView(showsIndicators: false) {
ForEach(self.items, id: \.self) { _ in
RowItem()
}
if (self.items.count == 0) {
HStack{
Spacer()
}
}
}
Run Code Online (Sandbox Code Playgroud)
观察到的空容器的行为是已知的ScrollView- 它需要一些东西(初始内容)来计算初始大小,因此以下内容解决了您的代码行为
@Published var items: [String] = [""]
Run Code Online (Sandbox Code Playgroud)
一般来说,在这种情况下,我更喜欢在数组中存储一些“易于检测的初始值”,当第一个“真实模型值”出现时将其删除,并在最后一个消失时再次添加。希望这会有所帮助。
| 归档时间: |
|
| 查看次数: |
2956 次 |
| 最近记录: |