Swift:如何使异步调用(附加到数组)串行运行?

标签 swift asynchronous grand-central-dispatch

问题

我遇到了一个问题,我有一个网络调用循环(称为 grabImage),所有调用都将它们的回调数据附加到同一个数组,并且我正确地使用了一个调度组来不离开函数直到完成所有网络调用(直到组的进入/离开平衡)。但是,我无法控制回调编辑上述数组的顺序,并且在数据中获得随机排序。我如何确保这些回调(全部发生在单独的线程中)串行运行以保持全局数组中的顺序?

我尝试过的

我已经尝试过明显的使用串行队列,但是,因为 grabImage 函数会自行转义,我认为串行队列可能认为它在进入回调之前已经执行完毕

相关代码

//function to grab the uploaded pics of a user and store them
func fetchAllImages(_ userPicArray: [String?], _ completion: @escaping ([UIImage]) -> ()) {
    var images: [UIImage] = [] //array these async calls are appending to
    for photoLink in userPicArray {
        //if the picture (link) exists
        if photoLink != nil {
            //make sure to append to the array asynchronously

            appendImagesSQ.sync { //my attempt to run serially

                //grab image and add it to the resImages array
                self.grabImage(photoLink!) { (image) in //grabImage itself escapes
                    self.grabImageDispatchGroup.leave()
                    images.append(image)
                }

            }
        }
    }
    grabImageDispatchGroup.notify(queue: grabImageSQ) {
        completion(images)
    }
}

最佳答案

让它们按顺序运行并不是解决这个问题的最好方法。当然,你会把它们整理好,但它会比你想要的慢得多。相反,同时启动它们,将结果存储在字典中,然后当你全部完成后,按顺序从字典中检索结果,例如

func fetchAllImages(_ userPicArray: [String?], _ completion: @escaping ([UIImage]) -> ()) {
    var images: [String: UIImage] = [:] //dictionary these async calls are inserted to

    let group = DispatchGroup()

    let photoLinks = userPicArray.compactMap { $0 }
    for photoLink in photoLinks {
        group.enter()
        grabImage(photoLink) { image in
            images[photoLink] = image
            group.leave()
        }
    }

    group.notify(queue: .main) {
        let sortedImages = photoLinks.compactMap { images[$0] }
        completion(sortedImages)
    }
}

顺便说一下,您的 grabImage 似乎返回了一个非可选的。但是,如果请求失败怎么办?您仍然需要调用完成处理程序。确保即使没有检索到图像,grabImage 也会调用闭包(例如,将 image 属性设为可选,无论成功或失败都调用闭包)。

此外,grabImage 是否在主队列中调用其完成处理程序?如果不是,您需要确保在串行队列上调用它,以确保线程安全,否则将需要此 images 字典的一些同步。

关于Swift:如何使异步调用(附加到数组)串行运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62251830/

相关文章:

c# - 可以为抽象类的子类创建静态构造函数吗?

ios - iOS 中的 GCD 总是创建新线程

ios - 对可选属性感到困惑——如何更好地编写这段代码?

ios - 如何阻止多个 AVAudioPlayer 快速播放?

iOS:在应用程序中使用的音频文件听起来比在应用程序外播放时更刺耳

xaml - Windows 8. Metro 应用程序。 XAML 异步绑定(bind)

ios - SWIFT UITableView - 原型(prototype)单元格中的多行转至另一个 UITableView

python - 在普通函数中调用异步函数

ios - 按顺序异步下载图片

iOS。我如何在 Grand Central Dispatch 的上下文中处理 URL 身份验证质询