SwiftUI ScrollView 没有更新?
Posted
技术标签:
【中文标题】SwiftUI ScrollView 没有更新?【英文标题】:SwiftUI ScrollView not getting updated? 【发布时间】:2019-11-13 05:35:54 【问题描述】:目标
获取要在scrollView
中显示的数据
预期结果
实际结果
替代方案
使用List
,但不够灵活(不能去掉分隔符,不能多列)
代码
struct Object: Identifiable
var id: String
struct Test: View
@State var array = [Object]()
var body: some View
// return VStack // uncomment this to see that it works perfectly fine
return ScrollView(.vertical)
ForEach(array) o in
Text(o.id)
.onAppear(perform:
self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
)
【问题讨论】:
我在 Xcode 11.1、ios 13.1、Swift 5 上对此进行了测试,得到了预期的结果(尽管滚动视图位于顶部而不是中心)。 你也不需要关键字return
有趣,我正在使用 Xcode 11.2、iOS 13.2、Swift 5
是的,我之前有一个print
声明,因此return
我使用此代码向 Apple 提交了 FB8101550。感谢您记录此错误并制作一个小型复制案例。后代:github.com/jgale/SwiftUIScrollViewUpdateBug
【参考方案1】:
解决这个问题的一个不那么老套的方法是将 ScrollView 包含在一个 IF 语句中,以检查数组是否为空
if !self.array.isEmpty
ScrollView(.vertical)
ForEach(array) o in
Text(o.id)
【讨论】:
【参考方案2】:我发现如果状态初始化为某个值而不是空数组,它可以按预期工作(Xcode 11.2)。在这种情况下,更新工作正常,初始状态无效。
struct TestScrollViewOnAppear: View
@State var array = [Object(id: "1")]
var body: some View
ScrollView(.vertical)
ForEach(array) o in
Text(o.id)
.onAppear(perform:
self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
)
【讨论】:
适用于简单情况,在我的情况下,我在onAppear
有一个网络调用,因此使用虚拟数据初始化滚动视图可能会出现问题
正确,但是这种情况可以在代码中进行逻辑处理,因为初始对象可以是一些容易检测到的存根,可以有条件地显示诸如“加载”等内容。对我来说,这已经足够了……非常值得分享。【参考方案3】:
我发现的一个解决方法是在滚动视图中添加一个“不可见”Rectangle
,并将width
设置为大于scrollView
中数据宽度的值
struct Object: Identifiable
var id: String
struct ContentView: View
@State var array = [Object]()
var body: some View
GeometryReader geometry in
ScrollView(.vertical)
Rectangle()
.frame(width: geometry.size.width, height: 0.01)
ForEach(array) o in
Text(o.id)
.onAppear(perform:
self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
)
【讨论】:
【参考方案4】:预期的行为发生在 Xcode 11.1
上,但不会出现在 Xcode 11.2.1
上
我在ScrollView
中添加了frame
修饰符,使ScrollView
出现
struct Object: Identifiable
var id: String
struct ContentView: View
@State var array = [Object]()
var body: some View
ScrollView(.vertical)
ForEach(array) o in
Text(o.id)
.frame(height: 40)
.onAppear(perform:
self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
)
【讨论】:
很遗憾无法在模拟器上的 iOS 13.2 上运行【参考方案5】:借用 paulaysabellemedina,我想出了一个小助手视图,它可以按照我的预期处理事情。
struct ScrollingCollection<Element: Identifiable, Content: View>: View
let items: [Element]
let axis: Axis.Set
let content: (Element) -> Content
var body: some View
Group
if !self.items.isEmpty
ScrollView(axis)
if axis == .horizontal
HStack
ForEach(self.items) item in
self.content(item)
else
VStack
ForEach(self.items) item in
self.content(item)
else
EmptyView()
【讨论】:
以上是关于SwiftUI ScrollView 没有更新?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - ScrollView 没有一直滚动到底部
有没有办法在 SwiftUI 中制作分页的 ScrollView?