我如何检查我的所有图像何时已下载?

How can I check when all my images have downloaded?

我正在下载几张图片并缓存它们。然后我调用缓存的图像并将它们作为子视图添加到我的 scrollView(它是水平的,使用页面控制器)。当视图出现而无需任何其他操作时,我想同时执行这两项操作。不幸的是,它已经在图像被缓存之前添加了子视图,因为它在图像下载时通过了代码。因此,没有添加任何内容作为子视图。

当我在视图出现时下载并缓存图像并在按下按钮时将它们添加为子视图时,它会起作用,但我希望它自动起作用。

我不确定我的代码是否有助于更好地理解,但在这里。

这是我下载图片的代码

   func downloadImage(url: URL) {
        let dataTask = URLSession.shared.dataTask(with: url) { data, responseURL, error in
            
            var downloadedImage:UIImage?
  
            if let data = data {
                downloadedImage = UIImage(data: data)
            }
            // if download actaully got an image
            if downloadedImage != nil {
                self.sum += 1 

                self.cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString) // cache the image
      
                // add the url as value to the dictionary
                self.imageURLS[self.sum] = url.absoluteString
            }
        }
        dataTask.resume()
    }

这就是我用来添加子视图的方法

func appendImages(){
        // sort the values of the dictionary by the greatest
        let sortedImageURLs = Array(imageURLS.keys).sorted(by: >)
        var stringURLs = [String]() // empty string array to append the URL's
        
        // for loop which goes through all integers in "creation Date" array
        for keys in sortedImageURLs {
            let url: String? = imageURLS[keys] // url which is connected to the key
            stringURLs.append(url!) // append the url to the url array
        }
        // -> the url string array starts with the latest loaded url
        
        var originSubview = 0 // counter of the origin of the subviews
        for urls in stringURLs {
            // 1.
            frame.origin.x = scrollView.frame.size.width * CGFloat(originSubview)
            frame.size = scrollView.frame.size
            // 2.
            let imageView = UIImageView(frame: frame)
            
            // get the image which is cahed under the url
            let image = cache.object(forKey: urls as NSString)
            
            // set the image of image view as the cached image
            imageView.image = image
            // and add that image view as a subview to the scrollView
            scrollView.addSubview(imageView)
            
            // increase counter variable by one
            //-> next images origin is at the end of the image before
            originSubview += 1
        }
        
        // 3.
        scrollView.contentSize = CGSize(width: ((scrollView.frame.size.width) * CGFloat(specialsCounter)), height: (scrollView.frame.size.height))
        scrollView.delegate = self
        pageControl.numberOfPages = specialsCounter
    }

您可以使用 DispatchGroup 在所有下载完成时发出通知。 基本上你在开始下载之前 enter() 和下载完成时 leavenotify 将在所有 entered 任务具有 left

时触发

这是一个关于如何做的例子。我为您的 downloadImage 函数制作了一个完成块。

let dispatchGroup = DispatchGroup()

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    for url in imageUrls {
        self.dispatchGroup.enter()
        downloadImage(url: url) {
            self.dispatchGroup.leave()
        }
    }
    
    self.dispatchGroup.notify(queue: .main) {
        //All images has been downloaded here
    }
    
}

downloadImage 函数完成:

func downloadImage(url: URL, completion: () -> ()) {
      let dataTask = URLSession.shared.dataTask(with: url) { data, responseURL, error in
          
          var downloadedImage:UIImage?

          if let data = data {
              downloadedImage = UIImage(data: data)
          }
          // if download actaully got an image
          if downloadedImage != nil {
              self.sum += 1

              self.cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString) // cache the image
    
              // add the url as value to the dictionary
              self.imageURLS[self.sum] = url.absoluteString
              completion()
          } else {
              completion()
          }
      }
      dataTask.resume()
  }