我无法从Firebase存储中获取数组并放入另一个阵列swift



我想从Firebase存储中获取文件夹和图像。在这个代码上,除了一个瞬间,其他都可以工作。我无法在数组self.collectionImagesArray中附加数组self-collectionImages。我没有错误,但数组self-CollectionImagesArrays为空

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)
}
}
}

如果我把self.collectionImagesArray.append(self.collection Images(放在闭包中,它会起作用,但不是我想要的

问题是由于调用downloadURL是一个异步操作,因为它需要对服务器进行调用。当调用发生时,您的主代码会继续,以便用户可以继续使用该应用程序。然后,当服务器返回一个值时,将调用您的闭包/完成处理程序,该处理程序将URL添加到数组中。因此,您的print("(self.collectionImagesArray)")发生在调用self.collectionImages.append(img)之前。

您还可以从打印语句在输出中的出现顺序中看到这一点。您将首先看到完整的空数组,然后才看到print("(self.collectionImages)")输出。

这个问题的解决方案总是一样的:你需要确保你只在所有URL都添加到数组中后才使用它。有很多方法可以做到这一点,但一个简单的方法是检查你的URL数组是否与回调中的result.items长度相同:

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

另请参阅:

  • 如何等待从Firebase Storage下载完成后再执行完成swift
  • 在异步工作完成之前返回数据的闭包
  • 从异步调用返回图像
  • SwiftUI:异步更改图像后视图不更新