I have a project where I want to display badges (an image with a title) in a horizontal scroll view. The data for the badges is stored in a Firestore database. My code can fetch the data and show the badges in a horizontal scroll view. At the moment the badges are in a random order and I want to be able to sort them so they are in the correct order. For example:
Currently I have 4 badges, These include:
10k steps badge, 20k steps badge, 30k steps badge, 40k steps badge
This is the order I want them to be displayed in the horizontal scrollview however they are in a random order.
How can I order this data correctly? I am currently using a ForEach to Loop through the data.
My Model for the badges is as follows:
struct FitnessBadge: Identifiable {
var id: String
var fitness_badge_name: String
var fitness_badge_details: String
var fitness_badge_image: String
}
The View for the Badges is as follows:
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)
}
}
}
}
How the badges are being displayed in a scroll view is as follows:
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)
})
}
}
}
})
I want it to go: 10k steps, 20k steps, 30k steps etc.
The AchievementPageModel.filteredFitnessBadges array is as follows:
class AchievementPageViewModel: NSObject, ObservableObject {
// Fitness Badges Data...
@Published var fitnessBadges: [FitnessBadge] = []
@Published var filteredFitnessBadges: [FitnessBadge] = []
}
And the fetching data for the badges is as follows:
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
}
}
CodePudding user response:
In the view where badges are being displayed, replace:
ForEach(AchievementPageModel.filteredFitnessBadges)
with:
ForEach(AchievementPageModel.filteredFitnessBadges.sorted { $0.fitness_badge_name < $1.fitness_badge_name })
This will sort by the field fitness_badge_name
. I have assumed that's the field that contains "10k", "20k"... if the key is another field, just replace the variable in the .sorted()
function.