gpt4 book ai didi

ios - forEach 循环跳过最后一项

转载 作者:行者123 更新时间:2023-11-30 11:57:38 25 4
gpt4 key购买 nike

这个 forEach 循环有时有效,有时会跳过。我不确定我在这里做错了什么。循环将跳过最后一项并且永远不会退出。所以完成 block 根本不会被触发。

我正在使用 firebase、Eureka 表单及其 ImageRow 扩展。

我希望能在这里得到一些帮助。

//MARK: - Get Form Values
var returnedValues: [String: Any] = [:]
fileprivate func getFormValues(values: [String: Any], completion: @escaping ([String:Any])->()) {

if let name = values["name"] as? String,
let description = values["description"] as? String,
let images = values["images"] as? [UIImage],
let category = values["category"] as? String,
let price = values["price"] as? Double,
let deliveryFee = values["deliveryFee"] as? Double,
let deliveryAreas = values["deliveryArea"] as? Set<String>,
let deliveryTime = values["deliveryTime"] as? String {

guard let uid = Auth.auth().currentUser?.uid else { return }
var imagesData = [[String: Any]]()
var counter = 0

images.forEach({ (image) in

let imageName = NSUUID().uuidString
let productImageStorageRef = Storage.storage().reference().child("product_images").child(uid).child("\(imageName).jpg")
var resizedImage = UIImage()

if image.size.width > 800 {
resizedImage = image.resizeWithWidth(width: 800)!
}

if let uploadData = UIImageJPEGRepresentation(resizedImage, 0.5) {
productImageStorageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil {
print("Failed to upload image: \(error?.localizedDescription ?? "")")
return
}

//Successfully uploaded product Image
print("Successfully uploaded product Image")
if let productImageUrl = metadata?.downloadURL()?.absoluteString {
counter += 1
let imageData: [String: Any] = [imageName: productImageUrl]
imagesData.append(imageData)

if counter == images.count {
let deliveryAreasArr = Array(deliveryAreas)
self.returnedValues = ["name": name, "description": description, "images": imagesData , "category": category, "price": price, "deliveryFee": deliveryFee, "deliveryArea": deliveryAreasArr, "deliveryTime": deliveryTime, "creationDate": Date().timeIntervalSince1970, "userId": uid]
completion(self.returnedValues)
}

}

})
}
})

} else {

let alert = UIAlertController(title: "Missing Information", message: "All fields are required. Please fill all fields.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
alert.dismiss(animated: true, completion: nil)
}))
UIActivityIndicatorView.stopActivityIndicator(indicator: self.activityIndicator, container: self.activityIndicatorContainer, loadingView: self.activityIndicatorLoadingView)
self.present(alert, animated: true, completion: nil)
}
}

最佳答案

for 循环内有许多 if 语句,可能会导致 counter 不增加。如果其中任何一个失败,那么您将永远不会调用完成处理程序。

据我所知,您正在使用计数器来尝试了解所有异步任务何时完成,但调度组是更好的解决方案。

在所有路径中调用完成处理程序也很重要;例如当初始 guard 失败或在初始 ifelse 子句中 - 您的完成处理程序可能应该接受 Error 参数,以便它知道存在问题。

//MARK: - Get Form Values

fileprivate func getFormValues(values: [String: Any], completion: @escaping ([String:Any]?)->()) {
var returnedValues: [String: Any] = [:]

if let name = values["name"] as? String,
let description = values["description"] as? String,
let images = values["images"] as? [UIImage],
let category = values["category"] as? String,
let price = values["price"] as? Double,
let deliveryFee = values["deliveryFee"] as? Double,
let deliveryAreas = values["deliveryArea"] as? Set<String>,
let deliveryTime = values["deliveryTime"] as? String {

guard let uid = Auth.auth().currentUser?.uid else {
completion(nil)
return
}
var imagesData = [[String: Any]]()

let dispatchGroup = DispatchGroup() // Create a Dispatch Group

images.forEach({ (image) in

let imageName = NSUUID().uuidString
let productImageStorageRef = Storage.storage().reference().child("product_images").child(uid).child("\(imageName).jpg")
var resizedImage = UIImage()

if image.size.width > 800 {
resizedImage = image.resizeWithWidth(width: 800)!
}

if let uploadData = UIImageJPEGRepresentation(resizedImage, 0.5) {

dispatchGroup.enter() // Enter the group

productImageStorageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
guard error == nil else {
print("Failed to upload image: \(error?.localizedDescription ?? "")")
dispatchGroup.leave() // Leave the dispatch group if there was an error
return
}

//Successfully uploaded product Image
print("Successfully uploaded product Image")
if let productImageUrl = metadata?.downloadURL()?.absoluteString {
let imageData: [String: Any] = [imageName: productImageUrl]
imagesData.append(imageData)
}
dispatchGroup.leave() // Leave the dispatch group in normal circumstances
})
}
})

// Schedule a notify closure for execution when the dispatch group is empty

dispatchGroup.notify(queue: .main) {
let deliveryAreasArr = Array(deliveryAreas)
returnedValues = ["name": name, "description": description, "images": imagesData , "category": category, "price": price, "deliveryFee": deliveryFee, "deliveryArea": deliveryAreasArr, "deliveryTime": deliveryTime, "creationDate": Date().timeIntervalSince1970, "userId": uid]
completion(self.returnedValues)
}

} else {
completion(nil)
let alert = UIAlertController(title: "Missing Information", message: "All fields are required. Please fill all fields.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
alert.dismiss(animated: true, completion: nil)
}))
UIActivityIndicatorView.stopActivityIndicator(indicator: self.activityIndicator, container: self.activityIndicatorContainer, loadingView: self.activityIndicatorLoadingView)
self.present(alert, animated: true, completion: nil)
}
}

其他一些要点:

  • 传递结构体比传递字典更好。使用 struct 作为输入将消除函数开头的大量 if let ,因为您会知道值的类型并使它们成为非可选结构体的属性,您就会知道这些值是否存在。
  • 像这样的函数很少会发出警报;它通常只会通过完成返回一个错误,或者抛出返回给调用者以表明存在问题并让调用者处理它
  • 我不明白为什么 imagesData 需要是字典数组。数组中的每个字典只有一个条目,因此您可以只使用 [String:String] 字典(当您知道该字典是什么时,无需使用 Any类型将是。

关于ios - forEach 循环跳过最后一项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47622561/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com