循环不';t使用调度队列、iOS和Swift完成周期

循环不';t使用调度队列、iOS和Swift完成周期,ios,loops,grand-central-dispatch,Ios,Loops,Grand Central Dispatch,我有一个函数,它运行一个循环,为循环中的每个项触发另一个函数,但它似乎没有数组中的项运行那么多次 这是我的职责 func startLoop(completion: @escaping (_ finished: Bool) -> ()) { print("Tony items amount is \(tempImgUrls.count)") for item in tempImgUrls { dispatchGroup.enter()

我有一个函数,它运行一个循环,为循环中的每个项触发另一个函数,但它似乎没有数组中的项运行那么多次

这是我的职责

func startLoop(completion: @escaping (_ finished: Bool) -> ()) {


    print("Tony items amount is \(tempImgUrls.count)")
        for item in tempImgUrls {
            dispatchGroup.enter()
            print("Tony begin loop")
            let img = item["imgUrl"]
            let name = item["name"]
            downloadImages(img: img!, name: name!, completion: { (complete) in
                print("Tony mid loop")
                self.dispatchGroup.leave()
            })
        }

    dispatchGroup.notify(queue: DispatchQueue.main) {
        print("Tony end loop")
        completion(true)
        }
    }

func downloadImages(img: String, name: String, completion: @escaping (_ finished: Bool) -> ()) {


            imageShown.sd_setImage(with: URL(string: img), completed: { (image, error, cacheType, imageUrl) in

                let personImg = image!
                let personId = name
                let post = Person(personImage: personImg, personId: personId)

                self.finalImgUrls.append(post)
                completion(true)
                print("Tony array is with images person is \(self.finalImgUrls)")
                print("Tony items 2 amount is \(self.finalImgUrls.count)")

        })
    }
}
这是Console中的打印输出,正如您所看到的,它首先打印循环开始,然后是中间1次,最后是1次,最后在末尾附加一个项目,而不是像输入的那样4个项目

托尼的物品数量是4

托尼·贝京环路

托尼·贝京环路

托尼·贝京环路

托尼·贝京环路

托尼中环线

Tony array正在使用图像个人是[AppName.person]

Tony项目2的金额为1


你的代码正在运行。问题似乎在于
sd_setImage
只提供一次结果

如何测试

如果按如下方式使用
sd_setImage
的测试实现,则会得到预期结果:

class SomeClass {
    func sd_setImage(with url: URL?, completed: @escaping (UIImage?, Error?, String, URL) -> Void) {
        let random = Double(arc4random()) / Double(UINT32_MAX)
        DispatchQueue.main.asyncAfter(deadline: .now() + random, execute: {
            completed(UIImage(), nil, "a", url!)
        })
    }
}

当您使用
UIImageView
异步图像检索扩展时,当为同一图像视图请求另一图像时,它们总是会取消先前对该图像视图的请求。(这通常是设计上的,因为它可以防止图像请求被不再需要的相同图像视图的先前图像请求(例如,可以重用的表视图单元格中的图像视图)积压。)

问题在于,如果取消了图像检索,SDWebImage的
UIImageView
扩展不会调用其完成处理程序。这是一个API设计缺陷,IMHO,因为异步方法应始终调用其完成处理程序(如果请求被取消,则会出现“取消”错误代码)。但由于SDWebImage不这样做,循环的初始请求将被取消,而不是后续请求,因此,对早期迭代的
leave
调用将永远不会被调用。仅供参考,其他图像库(如)不会受到此设计缺陷的影响(尽管它有自己的问题)

但这就引出了你的意图是什么的问题。例如,如果希望连续查看图像序列,则在前一个图像检索完成之前,不应启动下一个图像检索(例如,在前一个图像的完成处理程序中启动下一个图像检索)。或者,您应该自己检索图像(不使用取消先前请求的扩展名
UIImageView
),并在那里对UI进行定时更新。但您几乎肯定不希望为同一图像视图启动多个并发图像更新