Swift:如何连续进行异步调用(附加到数组)运行?

Swift: How to make async calls (appending to an array) run serially?

问题

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

我试过的

我已经尝试过明显的使用串行队列,但是,因为 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 { [=10=] }
    for photoLink in photoLinks {
        group.enter()
        grabImage(photoLink) { image in
            images[photoLink] = image
            group.leave()
        }
    }

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

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

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