ios - Swift - 循环中的完成处理程序

标签 ios swift

<分区>

我有一个带有完成处理程序的方法

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 从来没有出现,因为甚至在我第一次打电话之前就已经检查返回了。我做错了什么,我该如何完成我想要完成的事情?

最佳答案

问题是您的for 循环将很快完成。事实上,如您所见,循环甚至在调用完成 block 之一之前就结束了。这就是异步处理的本质。

通过使用 DispatchGroup,您可以设置您的代码,使其仅在所有完成 block 完成后才执行代码块,而不管循环本身完成的速度有多快。

另请注意,您的循环中有两个级别的异步调用。

以下是您应该如何设置代码。另请注意,我修复了其他几个问题,例如 forced-unwraps。

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)
    }
}

关于ios - Swift - 循环中的完成处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50237680/

相关文章:

ios - Firebase 分析 : logging events to multiple projects

swift - 将 CAShapeLayer 转换为在 NSImageView 中使用

swift - 如何使用 Kingfisher 为项目中的所有 ImageView 设置指标类型?

ios - 未使用 Firebase UI 数据源调用 UICollectionView viewForSupplementaryElementOfKind

ios - 在 iOS 上将 ARKit 与 Metal 结合使用时如何过滤掉模糊图像?

ios - CNMutableContact 和 iOS 13 中的 note 和 imageData

arrays - 查找峰值元素(多个)SWIFT

ios - 如何检查 locationManager 是否更新了当前位置?

ios - xcode 6,调整 inputAccessoryView 的大小

ios - 通过导航 Controller 推送 Viewcontroller,显示黑屏