【问题标题】:How to apply Async/await (like javascript) in iOS Swift?如何在 iOS Swift 中应用 Async/await(如 javascript)?
【发布时间】:2019-04-03 12:22:49
【问题描述】:

我有以下代码结构,如何在后台线程上运行这段代码,并在 FIFO 中串行执行所有方法。

如何等待函数执行完它的所有语句然后移动到下一个函数?


func downloadImagesAndProcess(){
// i need these methods to execute one by one i.e when saveimages completes fully only then call resizeimages
saveImages()
resizeImages()
shareImgs()

}

func saveImages(){

// long async tasks

for (index, image) in (self.images.enumerated())! {
              
     KingfisherManager.shared.retrieveImage(with: URL(string:image.imageFile)!) { result in
                    
                    switch result {
                    case .success(let value):
                    self.saveImageDocumentDirectory(image: value.image, imageName: imgNameStr)

                    case .failure(let error):
                        print(error) // The error happens
                    }
                  
                }
              
            }

}

func resizeImages(){

// long running tasks

}

func shareimgs(){

//share
}

我需要这些方法一一执行,即当saveImages完全完成时才调用resizeImages

如何等待函数执行完它的所有语句然后移动到下一个函数?

【问题讨论】:

  • 你可以使用串行队列。
  • @jarvis12 串行队列不执行函数内的所有语句..它移动到其他函数
  • 对不起,没有任何实际代码很难帮助你;可能有不同的解决方案,您尝试过吗?
  • @RicoCrescenzio 我已经尝试过调度组和串行队列,但它们对我不起作用
  • 放上你正在使用的代码,不仅仅是方法声明

标签: ios swift concurrency grand-central-dispatch


【解决方案1】:

您可以将此框架用于 Swift 协程 - https://github.com/belozierov/SwiftCoroutine

当你调用 await 时,它不会阻塞线程,只会挂起协程,所以你也可以在主线程中使用它。

func saveImages() {
    DispatchQueue.main.startCoroutine {
        let manager = KingfisherManager.shared

        for (index, image) in (self.images.enumerated())! {
            let url = URL(string: image.imageFile)!

            let result = try Coroutine.await {
                manager.retrieveImage(with: url, completionHandler: $0)
            }

            switch result {
            case .success(let value):
                self.saveImageDocumentDirectory(image: value.image, imageName: imgNameStr)
            case .failure(let error):
                print(error)
            }
        }

        self.resizeImages()
    }
}

【讨论】:

    【解决方案2】:

    最简单的方法是调用下一个方法完成上一个

    func saveImages(){
    
        let group = DispatchGroup()
        for (index, image) in (self.images.enumerated())! {
            group.enter()
            KingfisherManager.shared.retrieveImage(with: URL(string:image.imageFile)!) { result in
                switch result {
                case .success(let value):
                    self.saveImageDocumentDirectory(image: value.image, imageName: imgNameStr)
                case .failure(let error):
                    print(error) // The error happens
                }
                group.leave()
            }
        }
        group.notify(queue: .main) {
            // do your stuff, check if every image has been downloaded
            self.resizeImages() // this will be called after the completion of the current task
        }
    }
    

    然后在resizeImages 我猜还有另一个完成处理程序,在里面你会调用shareImgs

    【讨论】:

    • 我使用DispatchGroup 加载多个图像,因为它们的下载同时开始,但是您必须等到每个过程完成。完成所有任务后,将调用通知。
    • 我使用了 DispatchGroup,但是当使用带有后台队列块的调度组时,它不会等待
    • 我在您的代码中看不到任何后台队列实现,除此之外我无能为力
    • 只是我想知道如何使用后台队列等待和串行执行方法?
    • 为什么你把这个循环放在后台队列中? KingfisherManager.shared.retrieveImage 已经在另一个队列中运行(否则不会有任何完成处理程序)
    猜你喜欢
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 2021-08-27
    • 2022-11-18
    相关资源
    最近更新 更多