在 for 循环中使用异步调用处理完成
Handle completion with asynchronous call in for loop
我有一个应该有一个 completion-handler
的函数,只有当它里面的所有东西都真正完成时才应该调用它。那是我的职能:
static func getWishes(dataSourceArray: [Wishlist], completion: @escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
for list in dataSourceArray {
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
completion(true, dataSourceArrayWithWishes)
print("success")
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
}
问题出在imageView.kf.setImage...
现在我在第一个 .success
之后调用 completion
,但是只有在 for-loop
和所有 setImages
都完成时才能完成该功能。我现在已经尝试了几件事,但我无法让它发挥作用。所以我想知道这种情况下的最佳做法是什么?
下面是如何使用 DispatchGroup
的...您需要 DispatchGroup
才能在 asynchronous
循环结束时得到通知
static func getWishes(dataSourceArray: [Wishlist], completion: @escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
let group = DispatchGroup()
for list in dataSourceArray {
group.enter()
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
defer{ group.leave() }
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
group.enter()
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
defer{ group.leave() }
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
group.notify(queue: DispatchQueue.main) {
completion(true, dataSourceArrayWithWishes)
print("success")
}
}
我有一个应该有一个 completion-handler
的函数,只有当它里面的所有东西都真正完成时才应该调用它。那是我的职能:
static func getWishes(dataSourceArray: [Wishlist], completion: @escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
for list in dataSourceArray {
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
completion(true, dataSourceArrayWithWishes)
print("success")
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
}
问题出在imageView.kf.setImage...
现在我在第一个 .success
之后调用 completion
,但是只有在 for-loop
和所有 setImages
都完成时才能完成该功能。我现在已经尝试了几件事,但我无法让它发挥作用。所以我想知道这种情况下的最佳做法是什么?
下面是如何使用 DispatchGroup
的...您需要 DispatchGroup
才能在 asynchronous
循环结束时得到通知
static func getWishes(dataSourceArray: [Wishlist], completion: @escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
let group = DispatchGroup()
for list in dataSourceArray {
group.enter()
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
defer{ group.leave() }
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
group.enter()
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
defer{ group.leave() }
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
group.notify(queue: DispatchQueue.main) {
completion(true, dataSourceArrayWithWishes)
print("success")
}
}