我有一个带有完成处理程序的方法
func postLandGradingImages(cellHolder: Array<ImagesData>, completionHandler:@escaping (_ result:Bool) -> Void) {
//Define bool for returning data
var returnedResults = false
//Call API
WebService().postLandGradingImages(cellHolder)
{
(result: Bool) in
DispatchQueue.main.async {
//Return our results
returnedResults = result
completionHandler(returnedResults)
}
}
}
我在循环中调用此方法,如下所示:
for asset: PHAsset in photoAssets
{
self.postLandGradingImages(cellHolder: [ImagesData(jobNo: self.JobNo, ImageBytes: imageStr)]) { result in
}
}
我想要做的是,如果在某些时候失败,显示警告并停止循环,循环完成后我的所有调用返回true,最后显示警告。
这就是我的尝试:
var returned = false
for asset: PHAsset in photoAssets
{
imageManager.requestImage(for: asset, targetSize: CGSize(width: asset.pixelWidth, height: asset.pixelHeight), contentMode: .aspectFill, options: options, resultHandler: { (image, info) in
let imageData:Data = UIImagePNGRepresentation(image!)!
let imageStr = imageData.base64EncodedString()
self.postLandGradingImages(cellHolder: [ImagesData(jobNo: self.JobNo, ImageBytes: imageStr)]) { result in
returned = result
if(returned == false)
{
self.customAlert(title: "Error", message: "There was an error when saving data, please try again later.")
}
}
})
}
if(returned == true)
{
self.customAlert(title: "Error", message: “All Good“)
}
但是我的警告说All Good永远不会出现,因为在我第一次打电话之前,他们会被检查。我做错了什么,我如何完成我想要完成的任务?
答案 0 :(得分:2)
问题是你的for
循环会很快完成。实际上,正如您所见,循环将在完成一个完成块之前完成。这是异步处理的本质。
通过使用DispatchGroup
,您可以设置代码,这样只有在所有完成块完成后,它才会执行代码块,无论循环本身完成的速度有多快。
另请注意,循环内部有两级异步调用。
以下是设置代码的方法。另请注意,我修复了其他几个问题,例如强制解包。
var returned = true // assume success for all
let group = DispatchGroup()
for asset in photoAssets {
group.enter() // for imageManager
imageManager.requestImage(for: asset, targetSize: CGSize(width: asset.pixelWidth, height: asset.pixelHeight), contentMode: .aspectFill, options: options, resultHandler: { (image, info) in
if let image = image, let let imageData = UIImagePNGRepresentation(image) {
let imageStr = imageData.base64EncodedString()
group.enter()
self.postLandGradingImages(cellHolder: [ImagesData(jobNo: self.JobNo, ImageBytes: imageStr)]) { result in
if !result {
returned = false // we had a failure
}
group.leave()
}
}
group.leave() // imageManager
})
}
group.notify(queue: DispatchQueue.main) {
if returned {
self.customAlert(title: "Success", message: “All Good“)
} else {
self.customAlert(title: "Error", message: "There was an error when saving data, please try again later.")
}
}
完成所有这些后,您需要更新postLandGradingImages
。没有必要将主队列用于完成处理程序。
func postLandGradingImages(cellHolder: Array<ImagesData>, completionHandler:@escaping (_ result:Bool) -> Void) {
//Call API
WebService().postLandGradingImages(cellHolder) { (result: Bool) in
//Return our results
completionHandler(result)
}
}