如果顶部有 header 视图,如何在 SwiftUI List 下正确显示数据

How to display data correctly under SwiftUI List if there is a header view on top

我在使用 Xcode 11.6

的 SwiftUI List{} 函数中发现了一个奇怪的行为

如果我在列表顶部添加一个视图,数据就会混淆。

如果我删除俯视图,它会恢复正常。

如果我需要顶视图,关于这个问题有什么解决方法吗?

一个演示下载:https://github.com/BellRinging/bugDemo.git

代码示例:

import SwiftUI



  struct GameView: View {
            
    @ObservedObject var viewModel: GameViewModel
    @State var isShowing : Bool = false
    
    init(){
        viewModel = GameViewModel.shared
        print("init Game")
    //        viewModel.status = .loading
    //        viewModel.onInitialCheck()
        
    }


    var body: some View {
        NavigationView{
            VStack{
                //if there is a top view , The list Item mixd up
                VStack{
                    Text("Top Area").foregroundColor(Color.white)
                }.background(Color.red).frame(height:100)

            GameViewListHistoryArea(sectionHeader: self.viewModel.sectionHeader, games: self.viewModel.textItems)
            Spacer()
                
            }
            .navigationBarTitle("", displayMode: .inline)
  

          }
        }
    }



    struct GameViewListHistoryArea: View {
        
        @ObservedObject var viewModel: GameViewListAreaViewModel
    
        init(sectionHeader: [String],games:[String:[String]]){
            viewModel = GameViewListAreaViewModel(sectionHeader: sectionHeader, games: games)
        }
    
        var body: some View {
            VStack{
                List {
                    ForEach(self.viewModel.sectionHeader, id: \.self) { period in
                        Section(header: self.sectionArea(period:period)) {
                            ForEach(0 ..< self.viewModel.games[period]!.count ,id: \.self) { index in
                                Text("\(period) \(index)")
                            }
                        }
                    }
                }
            }
        }
    
        func sectionArea(period : String) -> some View {
            HStack{
                Text(period)
                Spacer()
            }
        }
    
    }



class GameViewListAreaViewModel: ObservableObject {
    
    
    var sectionHeader : [String]
    var games : [String:[String]]
    
    init(
        sectionHeader: [String],
        games:[String:[String]]){
        self.sectionHeader = sectionHeader
        self.games = games
    }
    
    
}


class GameViewModel: ObservableObject {
    
    static let shared = GameViewModel()
    
    
    @Published var textItems: [String:[String]] =  [:]
    @Published var sectionHeader : [String] = []
    
    init() {
        loadGame()
    }
    
    
    func loadGame(){
        self.textItems = self.makeRecord()
        self.sectionHeader = self.textItems.keys.sorted(by: >)
    }

    func makeRecord() -> Dictionary<String,[String]>{
        
        var dict : Dictionary<String,[String]> = [:]
        
        let jul20 = ["20200720","20200717","20200716","20200712","20200710","20200709","20200703"]
        let jun20 = ["20200630","20200628","20200620","20200614","20200606"]
        let may20 = ["20200531","20200529","20200527","20200524","20200520","20200519","20200517","20200515","20200513","20200509","20200507","20200502"]
        let apr20 = ["20200429","20200427","20200424","20200421","20200418","20200413","20200410","20200409","20200406","20200403","20200401"]
        let mar20 = ["20200329","20200327","20200322","20200320","20200315","20200313","20200307","20200305"]
        let feb20 = ["20200228","20200226","20200221","20200219","20200212","20200210"]
        
        dict["202007"] = jul20
        dict["202006"] = jun20
        dict["202005"] = may20
        dict["202004"] = apr20
        dict["202003"] = mar20
        dict["202002"] = feb20
        return dict
    }
   
}

期待这样的布局..用 VStack 替换列表

实际结果是这个奇怪的行为

适用于 Xcode 11.4 和 Xcode 12(我没有 11.6)。无论如何,问题的原因可能是由于每个部分中的行的非唯一 ID(使用有序索引),因此 List 决定不刷新它们。

尝试改用

Section(header: self.sectionArea(period:period)) {
    ForEach(Array(self.viewModel.games[period]!.enumerated()) ,id: \.1) { index, _ in
        Text("\(period) \(index)")
    }
}

注意:在提到的测试版本中,结果相同且正确。