循环的Swift 4完成处理程序不起作用

时间:2019-03-05 13:52:58

标签: ios swift

在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

4 个答案:

答案 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之类的东西来跟踪所有异步调用何时完成