【问题标题】:UIViewRepresentable Rows In List Disappearing in SwiftUI列表中的 UIViewRepresentable 行在 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 RotationContent in scrollview as a list item disappears when scrolling (swiftui), why?),但到目前为止没有真正的改进。 (当我在 ScrollView 中嵌入 ForEach 时,我遇到了不同的问题 - 我的两行中只显示了一个,并且按钮不再可点击)。

【问题讨论】:

    标签: ios swift swiftui


    【解决方案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 实例@,这仍然以相同的方式工作。即,列表单元格不会消失。
      猜你喜欢
      • 1970-01-01
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 2019-12-05
      • 2020-05-07
      相关资源
      最近更新 更多