SwiftUI ScrollView在进入屏幕之前过早渲染子视图

时间:2019-12-23 09:43:57

标签: swiftui

最近,我通过开发一个小应用程序开始研究ios / swiftui,该应用程序有一个卡片列表,用于显示从服务器加载的图片和消息。

我当时使用 List 来保存这些卡片,但是默认的列表“装饰”(分隔线,箭头,敲击效果)与我的卡片视图一起看起来不太好。我通过在 SceneDelegate 中添加以下代码来禁用它们:

UITableView.appearance().separatorColor = .clear
UITableViewCell.appearance().selectionStyle = .none

并且有某种技巧可以隐藏箭头:

List {
    ForEach(0..<self.store.data.count, id: \.self) { idx in
        NavigationLink(destination: DetailView(item: self.store.data[idx])) {
            EmptyView()
        }.frame(width: 0).opacity(0)
        ItemCard(item: self.store.data[idx])
    }
    BottomLoader().onAppear {
        if self.store.status != .loading {
            self.store.load() 
        }
    }
}

但是,问题在于,在SceneDelegate中隐藏列表的选择样式和分隔符颜色适用于App中的所有列表,而我确实有几个列表(例如设置中的一个)需要这些样式。

然后,我尝试将持卡人从 List 更改为 ScrollView ,但这又带来了另一个麻烦,即上一个视图的 onAppear 回调( BottomLoader)与ScrollView onAppear 同时被调用。

据我了解, onAppear 应该在呈现和显示视图时调用。 List作为项目持有者,不必计算所有项目的全高,这可能就是List仅呈现要进入屏幕的项目的原因。但是 ScrollView 确实需要知道所有项目的全高,这就是为什么所有项目都被渲染的原因。

下面是两个小段,用于显示List和ScrollView的不同行为:

List {
    ForEach(0..<100) { idx in
        Text("item # \(idx)").padding().onAppear { print("\(idx) on appear") }
    }
}
// only 18 logs printed

并且:

ScrollView {
    ForEach(0..<100) { idx in
        Text("item # \(idx)").padding().onAppear { print("\(idx) on appear") }
    }
}
// all 100 logs printed

有什么方法可以让ScrollView像List一样在它们要进入屏幕时呈现其子视图。 或者,有什么方法可以将这些默认样式禁用到特定的列表中,而不是全局禁用?

0 个答案:

没有答案