简体   繁体   English

如何在 iOS Swift 中应用异步/等待(如 javascript)?

[英]How to apply Async/await (like javascript) in iOS Swift?

I have a following code structure, how can I run this code on background thread and execute all the methods serially in FIFO.我有以下代码结构,如何在后台线程上运行此代码并在 FIFO 中串行执行所有方法。

How to wait for function to executes all its statements and then move to next function?如何等待函数执行其所有语句然后移动到下一个函数?


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
}

I need these methods to execute one by one ie when saveImages completes fully only then call resizeImages我需要这些方法一一执行,即当saveImages完全完成时才调用resizeImages

How to wait for function to executes all its statements and then move to next function?如何等待函数执行其所有语句然后移动到下一个函数?

You can use this framework for Swift coroutines - https://github.com/belozierov/SwiftCoroutine您可以将此框架用于 Swift 协程 - https://github.com/belozierov/SwiftCoroutine

When you call await it doesn't block the thread but only suspends coroutine, so you can use it in the main thread as well.当您调用 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()
    }
}

The easiest thing to do is call the next method inside the completion of the previous one最简单的就是在完成前一个里面调用next方法

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

Then in the resizeImages I guess there's another completion handler, inside that you'll call shareImgs然后在resizeImages我猜还有另一个完成处理程序,在里面你会调用shareImgs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM