I can not sort my array of custom objects. I have tried different swiftUI sorting methods but it doesn´t work and I suspect it has something to do with the struct model I have in my array. I save images in Firebase storage and saves their url:s together with some other data in an array of ImageModel, (my imageRefCollection in StudentModel). Then I fetch the images and stores them together with the other data (time and taskNr) in an array of ImageCollectionModel (my published var imageCollection). That is the array I want to sort.
This is my models: `
class StudentModel: Codable {
@DocumentID var id : String?
var name = ""
var district = ""
var school = ""
var courses = [Course]()
var activeCourse = Course()
var imageRefCollection = [ImageModel]()
}
struct ImageModel: Codable {
var time: String
var url: String
var taskNr: String
}
struct ImageCollectionModel {
var image:UIImage
var taskNr:String
var time:String
}
`
And here is my variable in my contentModel:
@Published var imageCollection = [ImageCollectionModel]()
And here is my function that I call onAppear of my View where I show all the images. I want to show them sorted by time (which is a string, that I can sort when I just try that in testing) but when I try to sort my ImageCollection-array, it doesnt work.
`
func getAllImages() {
let storageRef = Storage.storage().reference()
self.imageCollection = [ImageCollectionModel]()
if !student.imageRefCollection.isEmpty {
for image in student.imageRefCollection {
let fileRef = storageRef.child(image.url)
fileRef.getData(maxSize: 5*128*128) { imageData, error in
if error == nil && imageData != nil {
let fetchedImage = UIImage(data: imageData!) ?? UIImage()
let taskNr = image.taskNr
let time = image.time
let imageToAdd = ImageCollectionModel(image: fetchedImage, taskNr: taskNr, time: time)
self.imageCollection.append(imageToAdd)
}
}
}
imageCollection.sort {
$0.time < $1.time
}
}
}
}
`
When I fetch the images, using the for-loop, the for loop first loops all the times and then after that it fetches the images but then in some "random" order (I guess that has something to do with the asyncronus thing that I never has really understood). But, nevertheless, it doesnt matter if I only could sort the array after all the images has been fetched. I have tried .sort, .sort(by: but I havent got it to work.
This is how my view looks with my .sort attempt (the grid displays in rows from left to right):with .sort {$0.time < $1.time}
And this is how it looks with attempt imageCollection = imageCollection.sorted {$0.time < $1.time}
imageCollection = imageCollection.sorted {$0.time < $1.time}
Edit: Now I have tried to add DispatchGroup but I cant get it to work. My new code is:
`
func getAllImages() {
let storageRef = Storage.storage().reference()
if !student.imageRefCollection.isEmpty {
let group = DispatchGroup()
for image in self.student.imageRefCollection {
group.enter()
let fileRef = storageRef.child(image.url)
fileRef.getData(maxSize: 5*128*128) { imageData, error in
if error == nil && imageData != nil {
let fetchedImage = UIImage(data: imageData!) ?? UIImage()
let taskNr = image.taskNr
let time = image.time
let imageToAdd = ImageCollectionModel(image: fetchedImage, taskNr: taskNr, time: time)
self.imageCollection.append(imageToAdd)
}
}
group.leave()
}
group.notify(queue: DispatchQueue.global()) {
self.imageCollection.sort { $0.time < $1.time }
}
}
}
`
but that gives the following sort ... Sort after dispatchgroup try
What do I do wrong?
CodePudding user response:
You're not storing the result of your sorting in the variable. Use it like this:
imageCollection = imageCollection.sort { $0.time < $1.time }
CodePudding user response:
func getAllImages() {
let storageRef = Storage.storage().reference()
if !student.imageRefCollection.isEmpty {
let group = DispatchGroup()
for image in self.student.imageRefCollection {
group.enter()
let fileRef = storageRef.child(image.url)
fileRef.getData(maxSize: 5*128*128) { imageData, error in
if error == nil && imageData != nil {
let fetchedImage = UIImage(data: imageData!) ?? UIImage()
let taskNr = image.taskNr
let time = image.time
let imageToAdd = ImageCollectionModel(image: fetchedImage, taskNr: taskNr, time: time)
self.imageCollection.append(imageToAdd)
}
group.leave()
}
}
group.notify(queue: DispatchQueue.global()) {
self.imageCollection.sort { $0.time < $1.time }
}
}
}
}
You should move group.leave()
one line up. It should be executed just after async method returns response and append image to collection.
You should also convert String
time object to Date
object. For now .sort
is working on String
not on Date
, that's why it sorts your items in wrong order. Finally, check if you receive proper string dates from api.