Search code examples
swiftuiimageview

Showing UIImageView after finished loading


Currently I have a collection view of thumbnail images, Upon pressing that thumbnail image cell then it should call a function that would retrieve the Image data via API and shows the full image via the hidden ImageView.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            dataManager.downloadAttachment(id: attachments[indexPath.row].attachmentID)
            if dataManager.dataHolder != nil {
                attachmentImage.image = UIImage.init(data: dataManager.dataHolder!)
                attachmentImage.isHidden = false
            }
            print(attachments[indexPath.row].attachmentID)
        }

and

func downloadAttachment(id:Int) {
    let finalUrl = "\(urlAttachment)\(id)/data"
    if let url = URL(string: finalUrl){
        var request = URLRequest(url: url)
        request.setValue(apiKey, forHTTPHeaderField: header)
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: request) { (data, response, error) in
            if error != nil {
                print(error!)
                return
            }
            print("Attachment Downloaded")
            self.dataHolder = data
        }
        task.resume()
    }
}

The obvious issue with this is that the image wouldn't show on the first attempt since it would still be retrieving the image and the dataHolder would still be nil, But if I tap on the cell twice then the image will be shown correctly.

Is there a simple way to maybe just tap once and make it shows a place holder until finished downloading and update the place holder with an actual image accordingly? Or any other proper way to handle this?


Solution

  • You can use closures to achieve what you asked for. The updated code looks like this.

    func downloadAttachment(id:Int,completionHandler completion: @escaping ((Data)->Void)) {
    let finalUrl = "\(urlAttachment)\(id)/data"
    if let url = URL(string: finalUrl){
        var request = URLRequest(url: url)
        request.setValue(apiKey, forHTTPHeaderField: header)
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: request) { (data, response, error) in
            if error != nil {
                print(error!)
                return
            }
            print("Attachment Downloaded")
            self.dataHolder = data
            completion()
        }
        task.resume()
      }
    }
    

    Now in collectionViewDidSelectItemAt make this changes

    func collectionView (_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
          dataManager.downloadAttachment(id: attachments[indexPath.row].attachmentID,completionHandler: { data in
            if let cell = collectionView.cellForItem(at: indexPath),
                          let data = dataManager.dataHolder,
                          let image = UIImage.init(data: data){
                attachmentImage.image = image
                attachmentImage.isHidden = false
                }
         })
     }