列表中的 UIViewRepresentable 行在 SwiftUI 中消失

Posted

技术标签:

【中文标题】列表中的 UIViewRepresentable 行在 SwiftUI 中消失【英文标题】:UIViewRepresentable Rows In List Disappearing in SwiftUI 【发布时间】:2020-11-13 03:56:05 【问题描述】:

我有这个列表:

struct SignInList: View 
    @ObservedObject var model:SignInModel
    
    var body: some View 
        List(model.currentSignIns)  signIn in
            SignInRow(description: signIn)
        
    

使用此列表行:

struct SignInRow: View, Identifiable 
    let id = UUID()
    let description: SignInDescription
    
    var body: some View 
        VStack 
            ButtonView(view: description.button)
        
    


// Map a UIView to a View. Will be using this to hold a UIView based sign-in button
// https://developer.apple.com/tutorials/swiftui/creating-and-combining-views
struct ButtonView: UIViewRepresentable 
    let view: UIView
    
    func makeUIView(context: Context) -> UIView 
        return view
    
    
    func updateUIView(_ uiView: UIView, context: Context) 
    

但是当我滚动列表时,列表的单元格消失了:

Cells Disappearing

如果我将列表单元格更改为纯 SwiftUI,例如,

struct SignInRow: View, Identifiable 
    let id = UUID()
    let description: SignInDescription
    
    var body: some View 
        VStack 
            Rectangle()
        
    

我没有得到这个效果。滚动时单元格不会消失。

我已经尝试了一些关于 SO 的想法(例如,SwiftUI and ScrollView: Views Disappear After Device Rotation 和 Content in scrollview as a list item disappears when scrolling (swiftui), why?),但到目前为止没有真正的改进。 (当我在 ScrollView 中嵌入 ForEach 时,我遇到了不同的问题 - 我的两行中只显示了一个,并且按钮不再可点击)。

【问题讨论】:

【参考方案1】:

我认为@Asperi 走在正确的轨道上,List 是问题所在。我正在放弃使用它们。以下是现在对我有用的方法:

struct SignInList: View 
    @ObservedObject var model:SignInModel
    
    var body: some View 
        ScrollView() 
            ForEach(model.currentSignIns)  signIn in
                SignInRow(description: signIn)
                    .padding(.horizontal, 20)
            
        
    


struct SignInRow: View, Identifiable 
    let id = UUID()
    let description: SignInDescription
    
    var body: some View 
        VStack 
            ButtonView(view: description.button)
        .frame(height: 40)
    

【讨论】:

【参考方案2】:

我认为问题是因为 List 重用了行,所以它从 superview 中删除了您从外部注入的 UIView,但之后不要再次插入它(这不是可表示的工作方式),而只是更新。

一般模式是您应该提供数据,但视图应该在makeView 中创建并在updateView 中更新。

这是从您的代码中复制的一些简化演示。使用 Xcode 12.1 / ios 14.1 测试。

class SignInModel: ObservableObject 
    @Published var currentSignIns = (1..<100).map  "\($0)" 


struct SignInList: View 
    @ObservedObject var model = SignInModel()
    
    var body: some View 
        List(model.currentSignIns)  signIn in
            SignInRow(description: signIn)
        
    


struct SignInRow: View, Identifiable 
    let id = UUID()
    let description: String
    
    var body: some View 
        VStack 
            ButtonView(title: description)
        
    


struct ButtonView: UIViewRepresentable 
    let title: String
    
    func makeUIView(context: Context) -> UIView 
        let button = UIButton(type: .system)
        button.setTitle(title, for: .normal)
        return button
    
    
    func updateUIView(_ uiView: UIView, context: Context) 
    

【讨论】:

嘿,谢谢。也许这个的一些变化可以解决这个问题。我认为仍然缺少一些东西。如果您将新的 ButtonView 结构更改为具有生成 UIButton 的构造函数,并且在每次调用 UIButton 时仅返回相同的 UIButton 实例@,这仍然以相同的方式工作。即,列表单元格不会消失。

以上是关于列表中的 UIViewRepresentable 行在 SwiftUI 中消失的主要内容,如果未能解决你的问题,请参考以下文章

MapView:UIViewRepresentable 不以获取的列表为中心

更新 UIViewRepresentable 中的绑定

更新 SwiftUI 中的 inputAccessoryView (UIViewRepresentable)

TableView 重新加载不适用于 SwiftUI 中的 UIViewRepresentable

我如何使用Combine来跟踪UIViewRepresentable类中的UITextField更改?

可调整大小的 UITextView 的 sizeThatFits 在 UIViewRepresentable 中给出了错误的大小