Home > Software engineering >  I can't get array and put in the another array swift from Firebase storage
I can't get array and put in the another array swift from Firebase storage

Time:04-14

I want get folders and images from Firebase storage. On this code work all except one moment. I cant append array self.collectionImages in array self.collectionImagesArray. I don't have error but array self.collectionImagesArray is empty

class CollectionViewModel: ObservableObject {
@Published var collectionImagesArray: [[String]] = [[]]
@Published var collectionImages = [""]

init() {
  
   var db = Firestore.firestore()
   let storageRef = Storage.storage().reference().child("img")

   storageRef.listAll { (result, error) in
        if error != nil {
            print((error?.localizedDescription)!)
        }

        for prefixName in result.prefixes {
            let storageLocation = String(describing: prefixName)
            
            let storageRefImg = Storage.storage().reference(forURL: storageLocation)
        
            storageRefImg.listAll { (result, error) in
                if error != nil {
                    print((error?.localizedDescription)!)
                }
                
                for item in result.items {
                    // List storage reference
                    let storageLocation = String(describing: item)
                    let gsReference = Storage.storage().reference(forURL: storageLocation)
                    
                    // Fetch the download URL
                    gsReference.downloadURL { url, error in
                      if let error = error {
                        // Handle any errors
                        print(error)
                      } else {
                        // Get the download URL for each item storage location
                          let img = "\(url?.absoluteString ?? "placeholder")"
                          self.collectionImages.append(img)
                          print("\(self.collectionImages)")
                        }
                      }
                    }
                self.collectionImagesArray.append(self.collectionImages)
                print("\(self.collectionImagesArray)")
                }
            //
            self.collectionImagesArray.append(self.collectionImages)
        }
    }
}

If i put self.collectionImagesArray.append(self.collectionImages) in closure its works but its not what i want

CodePudding user response:

The problem is caused by the fact that calling downloadURL is an asynchronous operation, since it requires a call to the server. While that call is happening, your main code continues so that the user can continue to use the app. Then when the server returns a value, your closure/completion handler is invoked, which adds the URL to the array. So your print("\(self.collectionImagesArray)") happens before the self.collectionImages.append(img) has ever been called.

You can also see this in the order that the print statements occur in your output. You'll see the full, empty array first, and only then see the print("\(self.collectionImages)") outputs.

The solution for this problem is always the same: you need to make sure you only use the array after all the URLs have been added to it. There are many ways to do this, but a simple one is to check whether your array of URLs is the same length as result.items inside the callback:

...
self.collectionImages.append(img)
if self.collectionImages.count == result.items.count {
    self.collectionImagesArray.append(self.collectionImages)
    print("\(self.collectionImagesArray)")
}

Also see:

  • Related