如何排序数据数组并按该顺序显示它(Firebase 上的数据)

How to Order An Array Of Data and Display It In That Order (Data On Firebase)

我有一个项目,我想在水平滚动视图中显示徽章(带有标题的图像)。徽章的数据存储在 Firestore 数据库中。我的代码可以获取数据并在水平滚动视图中显示徽章。目前,徽章的顺序是随机的,我希望能够对它们进行排序,以便它们的顺序正确。例如:

目前我有4个徽章,包括:

10k 步徽章、20k 步徽章、30k 步徽章、40k 步徽章

这是我希望它们在水平滚动视图中显示的顺序,但它们的顺序是随机的。

如何正确排序这些数据?我目前正在使用 ForEach 循环访问数据。

我的徽章模型如下:

struct FitnessBadge: Identifiable {
    
    var id: String
    var fitness_badge_name: String
    var fitness_badge_details: String
    var fitness_badge_image: String
    
}

徽章的视图如下:

struct FitnessBadgeView: View {
    
    var fitnessBadge: FitnessBadge
    
    var body: some View {
        
        VStack(alignment: .center){
            
            // Downloading Image From Web...
            WebImage(url: URL(string: fitnessBadge.fitness_badge_image))
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 150, height: 150)
                .cornerRadius(15)
            
            HStack(spacing: 8){
                
                Text(fitnessBadge.fitness_badge_name)
                    
                    .font(.title2)
                    .fontWeight(.bold)
                    .foregroundColor(.black)
            }
            HStack(alignment: .center){
                
                Text(fitnessBadge.fitness_badge_details)
                    .font(.subheadline)
                    .foregroundColor(.gray)
                    .lineLimit(2)

                Spacer(minLength: 0)
            }
        }
        
    }
}

徽章在滚动视图中的显示方式如下:

ScrollView(.horizontal, showsIndicators: false, content: {
    
    VStack(alignment: .leading) {
    
    Text("Fitness Badges")
            .font(.title2)
            .fontWeight(.bold)
            .foregroundColor(.black)
            
    HStack(spacing: 10){
        
        ForEach(AchievementPageModel.filteredFitnessBadges){fitnessBadge in
            
            // Badge View...
            ZStack(alignment: Alignment(horizontal: .center, vertical: .top), content: {
                
                FitnessBadgeView(fitnessBadge: fitnessBadge)
                
                })
            }
        }
    }
})

我希望它走:10k 步、20k 步、30k 步等

AchievementPageModel.filteredFitnessBadges数组如下:

class AchievementPageViewModel: NSObject, ObservableObject {
 
    // Fitness Badges Data...
    @Published var fitnessBadges: [FitnessBadge] = []
    
    @Published var filteredFitnessBadges: [FitnessBadge] = []
    
}

徽章的获取数据如下:

func fetchFitnessBadgeData(){
    
    let db = Firestore.firestore()
    
    db.collection("FitnessBadges").getDocuments { (snap, err) in
        
        guard let fitnessBadgeData = snap else{return}
        
        self.fitnessBadges = fitnessBadgeData.documents.compactMap({ (doc) -> FitnessBadge? in
            
            let id = doc.documentID
            let name = doc.get("fitness_badge_name") as! String
            let image = doc.get("fitness_badge_image") as! String
            let details = doc.get("fitness_badge_details") as! String
            
            return FitnessBadge(id: id, fitness_badge_name: name, fitness_badge_details: details, fitness_badge_image: image)
        })
        
        self.filteredFitnessBadges = self.fitnessBadges
    }
}

在显示徽章的视图中,替换:

ForEach(AchievementPageModel.filteredFitnessBadges)

与:

ForEach(AchievementPageModel.filteredFitnessBadges.sorted { [=11=].fitness_badge_name < .fitness_badge_name })

这将按字段 fitness_badge_name 排序。我假设这是包含“10k”、“20k”的字段...如果键是另一个字段,只需替换 .sorted() 函数中的变量即可。

@HunterLion 给出了一个很好的答案,但它可能变得不切实际且不可扩展,因为它假设您正在将 FitnessBadges 中的所有文档加载到内存(数组)中以允许排序。

如果有 100 万个文档怎么办?那可能是大量的数据并且使设备不堪重负。

另一种选择是让 Firestore 完成繁重的工作;不用在您的应用程序上排序,让 Firestore 来做!

如果数据量较大, 最好让 Firebase 在服务器上排序并将排序后的数据呈现给您的应用程序,因为这样您就可以读取更小的数据 'chunks' 的数据通过分页。

更好的解决方案是像这样使用 order(by:

db.collection("FitnessBadges").order(by: "fitness_badge_name").getDocuments

在服务器上瞬间对数百万个文档进行排序,然后您可以获得所需的部分 - 例如记录 1-10,然后记录 11-20,然后它们将被排序。

供参考:Firestore Pagination