在swift 4中,我有一个使用完成处理程序循环的方法:
func loopImages(qa: QAClass, assets: [DKAsset], completion: ([PhotoClass]) -> Void) {
var imageCellHolder = [PhotoClass]()
for x in assets
{
x.fetchOriginalImage(completeBlock: { (image, info) in
let compressedImage = image?.resizeWithWidth(width: 800)
let imageData:Data = compressedImage!.jpegData(compressionQuality: 0.5)!
imageCellHolder.append(PhotoClass(job: String(self.selectedCommunity! + self.selectedLot!), photo: imageData, itemId: qa.itemId))
})
}
completion(imageCellHolder)
}
这是在循环完成后它应该调用的方法:
func loopFinished(imageCellHolder: [PhotoClass])
{
self.saveQAPhotos(cellHolder: imageCellHolder) { result in
print(result)
}
}
这就是我调用循环方法的方式:
self.loopImages(qa: qa, assets: assets, completion: self.loopFinished)
我的问题是在循环结束之前调用了完成处理程序方法(loopFinished)。
如果您想知道,fetchOriginalImage来自库DKImagePickerController https://github.com/zhangao0086/DKImagePickerController
答案 0 :(得分:5)
您需要DispatchGroup
才能完成多个不幸的任务
func loopImages(qa: QAClass, assets: [DKAsset], completion: ([PhotoClass]) -> Void) {
var imageCellHolder = [PhotoClass]()
let dispa = DispatchGroup()
for x in assets
{
dispa.enter()
x.fetchOriginalImage(completeBlock: { (image, info) in
let compressedImage = image?.resizeWithWidth(width: 800)
let imageData:Data = compressedImage!.jpegData(compressionQuality: 0.5)!
imageCellHolder.append(PhotoClass(job: String(self.selectedCommunity! + self.selectedLot!), photo: imageData, itemId: qa.itemId))
dispa.leave()
})
}
dispa.notify(queue: .main) {
completion(imageCellHolder)
}
}
答案 1 :(得分:5)
这样做的原因是,获取图像需要花费时间,实际的for循环很快完成,并且由于尚未获取图像而返回空数组。
考虑使用DispatchGroup
func loopImages(qa: QAClass, assets: [DKAsset], completion: ([PhotoClass]) -> Void) {
var imageCellHolder = [PhotoClass]()
let group = DispatchGroup()
for x in assets
{
group.enter()
x.fetchOriginalImage(completeBlock: { (image, info) in
let compressedImage = image?.resizeWithWidth(width: 800)
let imageData:Data = compressedImage!.jpegData(compressionQuality: 0.5)!
imageCellHolder.append(PhotoClass(job: String(self.selectedCommunity! + self.selectedLot!), photo: imageData, itemId: qa.itemId))
group.leave()
})
group.notify(queue: .main) {
completion(imageCellHolder)
}
}
}
DispatchGroup将等待所有图像完成下载,并在完成后调用完成
答案 2 :(得分:2)
您的任务是异步的。这意味着,您在请求数据后不会立即拥有数据。您需要等待,然后获取每个图像。
您可以避免使用DispatchGroup
,并且可以通过增加一些计数变量来跟踪是否已获取每个图像。在获取的图像数量与assets
数组的数量相同之后,您可以调用completion
func loopImages(qa: QAClass, assets: [DKAsset], completion: ([PhotoClass]) -> Void) {
var imageCellHolder = [PhotoClass]()
var count = 0 // <--
for x in assets {
x.fetchOriginalImage { image, info in
let compressedImage = image?.resizeWithWidth(width: 800)
let imageData:Data = compressedImage!.jpegData(compressionQuality: 0.5)!
imageCellHolder.append(PhotoClass(job: String(self.selectedCommunity! + self.selectedLot!), photo: imageData, itemId: qa.itemId))
/* -> */ count += 1
if count == assets.count {
completion(imageCellHolder)
}
}
}
}
答案 3 :(得分:0)
发生这种情况是因为fetchOriginalImage是异步的,您应该使用documentation之类的东西来跟踪所有异步调用何时完成