【发布时间】:2020-01-27 21:42:01
【问题描述】:
我正在尝试从 firebase 存储下载图像以显示在我的 collectionview 单元格中,但图像继续以随机顺序出现在单元格中。每个单元格都有一个从 firebase 存储(item1、item2 等)中检索到的标签,该标签每次都很好地显示在正确的单元格中。存储在 firebase 存储中的图像每个都将其存储 url 作为其在 firebase 数据库中各自项目名称的子项。
我成功地检索到每个图像 url,并下载所有图像并正确显示在单元格中,只是每次打开应用程序时它们都会以随机顺序出现,因此图像与项目名称标签。
我意识到我需要异步下载图像,因此每个图像在继续下一个之前完成加载到正确的单元格中,但我在这样做时遇到了麻烦。到目前为止,这是我的代码:
func downloadImg(completion: @escaping (UIImage?) -> ()) {
let ref = Database.database().reference().child("somePath")
ref.observeSingleEvent(of: .value) { (snapshot) in
for item in snapshot.children {
let snap = item as! DataSnapshot
let imageSnap = snap.childSnapshot(forPath: "img/storageUrl")
if let url = imageSnap.value as? String {
let someRef = self.storageRef.reference(forURL: url)
someRef.getData(maxSize: 10 * 10024 * 10024) { data, error in
if let error = error {
print(error)
} else {
let image = UIImage(data: data!)
DispatchQueue.main.async {
completion(image)
}
}
}
}
}
}
}
然后我在viewdidload中调用我的函数:
downloadImg { (completion) in
self.itemPicArray.append(completion!)
self.collectionView?.reloadData()
}
最后我将我的单元格图像视图设置为itemPicArray[indexPath.row]
就像我说的那样,这非常有效,只是图像不断随机显示。非常感谢帮助!
【问题讨论】:
-
看看developer.apple.com/documentation/dispatch/dispatchgroup。在下载下一个图像之前确保图像已经下载;而您当前的想法只是同时下载所有内容,并会给出不同的结果。
-
我试过这个,创建一个 DispatchGroup 实例并使用 .enter 和 .leave 但这似乎什么也没做。我应该改用 .wait 吗?还是别的什么?
-
我假设您还在 DispatchGroup 上使用了 .notify?在循环中进行异步调用时,我在使用 DispatchGroup 时遇到了困难。你在哪里 .leave() 你的 for-in-loop?
-
我没有,下次试试。我在函数的开头使用了 .enter,在 someRef.getData 中的 else 语句之后使用了 .leave。我对异步编程非常缺乏经验,所以我不太确定应该在哪里放置什么以及包含什么。
-
原谅这种糟糕的编辑风格;我在一个牢房里。我没有试过你的代码。但我想到的是:group.enter() 放在循环的顶部; group.leave() 放在 someRef.getData() 的右括号之前; group.notify() 放在循环的右括号之后。我猜你需要将你的图片作为 [UIImage](而不是 UIImage)发回,并相应地改变你的调用,比如 self.itemPicArray = completion。