提问者:小点点

当我下载了所有的图像时,我如何检查?


我正在下载几张图片并缓存它们。 然后,我正在回忆缓存的图像,并将它们作为子视图添加到我的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
    }

共1个答案

匿名用户

您可以使用DispatchGroup在所有下载完成时发出通知。 基本上,在开始下载之前要enter(),下载完成后要leave。 当所有输入的任务都有时,将触发通知

这里有一个关于如何做的例子。 我为你的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()
  }