2017-02-05 3 views
0

Я загружаю изображения с помощью API DropBox и отображая их в виде коллекции. Когда пользователь прокручивается, изображение либо исчезает из ячейки, а другое загружается или новое изображение перезагружается и заменяет изображение в ячейке. Как я могу предотвратить это? Я пробовал использовать SDWebImage, это держит изображения в правильном порядке, но все же изображения исчезают и перезагружаются каждый раз, когда они прокручиваются с экрана. Кроме того, я загружаю изображения напрямую, а не из URL-адреса, я бы предпочел не писать рабочий раунд, чтобы иметь возможность использовать SDWebImage.Ячейки перезагружают неправильные изображения при прокрутке в UI Collection View

Я бы опубликовал пример gif, но моя репутация слишком низкая.

Любая помощь будет приветствоваться :)

var filenames = [String]() 
var selectedFolder = "" 

    // image cache 
    var imageCache = NSCache<NSString, UIImage>() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    getFileNames { (names, error) in 
     self.filenames = names 
     if error == nil { 
      self.collectionView?.reloadData() 
      print("Gathered filenames") 
     } 
    } 

    collectionView?.collectionViewLayout = gridLayout 
    collectionView?.reloadData() 

override func viewWillDisappear(_ animated: Bool) { 
    super.viewWillDisappear(true) 

} 


func getFileNames(completion: @escaping (_ names: [String], _ error: Error?) -> Void) { 
    let client = DropboxClientsManager.authorizedClient! 
    client.files.listFolder(path: "\(selectedFolder)", recursive: false, includeMediaInfo: true, includeDeleted: false, includeHasExplicitSharedMembers: false).response { response, error in 
     var names = [String]() 
     if let result = response { 
      for entry in result.entries { 
       if entry.name.hasSuffix("jpg") { 
        names.append(entry.name) 

       } 
      } 
     } else { 
      print(error!) 
     } 
     completion(names, error as? Error) 
    } 
} 



func checkForNewFiles() { 
    getFileNames { (names, error) in 
     if names.count != self.filenames.count { 
      self.filenames = names 
      self.collectionView?.reloadData() 
     } 
    } 
} 

func downloadFiles(fileName: String, completion:@escaping (_ image: UIImage?, _ error: Error?) -> Void) { 

    if let cachedImage = imageCache.object(forKey: fileName as NSString) as UIImage? { 
     print("using a cached image") 
     completion(cachedImage, nil) 
    } else { 
     let client = DropboxClientsManager.authorizedClient! 
     client.files.download(path: "\(selectedFolder)\(fileName)").response { response, error in 
      if let theResponse = response { 
       let fileContents = theResponse.1 
       if let image = UIImage(data: fileContents) { 
        // resize the image here and setObject the resized Image to save it to cache. 
        // use resized image for completion as well 
        self.imageCache.setObject(image, forKey: fileName as NSString) 
        completion(image, nil) // completion(resizedImage, nil) 

       } 
       else { 
        completion(nil, error as! Error?) 
       } 

      } else if let error = error { 
       completion(nil, error as? Error) 
      } 
      } 
      .progress { progressData in 

     } 
    } 


} 



override func numberOfSections(in collectionView: UICollectionView) -> Int { 

    return 1 
} 


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 

    return self.filenames.count 
} 


override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCell 
    cell.backgroundColor = UIColor.lightGray 

    let fileName = self.filenames[indexPath.item] 
    let cellIndex = indexPath.item 
    self.downloadFiles(fileName: fileName) { (image, error) in 
     if cellIndex == indexPath.item { 
      cell.imageCellView.image = image 
      print("image download complete") 

     } 
    } 

    return cell 
} 

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 
    gridLayout.invalidateLayout() 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    imageCache.removeAllObjects() 
} 
+1

'если cellIndex == indexPath.item' есть ** всегда **' true'. – luk2302

ответ

0

Я установил ее. Это потребовало установки изображения ячейки = nil в функции cellForItemAt и отмены запроса изображения, если пользователь прокрутил ячейку с экрана до того, как она была закончена. Вот новый код cellForItemAt:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let fileId = indexPath.item 
    let fileName = self.filenames[indexPath.item] 

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCell 
    cell.backgroundColor = UIColor.lightGray 
    if cell.request != nil { 
     print("request not nil; cancel ", fileName) 
    } 

    cell.request?.cancel() 
    cell.request = nil 
    cell.imageCellView.image = nil 

    print ("clear image ", fileId) 
    self.downloadFiles(fileId:fileId, fileName: fileName, cell:cell) { (image, error) in 

     guard let image = image else { 
      print("abort set image ", fileId) 
      return 
     } 

     cell.imageCellView.image = image 

     print ("download/cache: ", fileId) 
    } 

    return cell 
}  
1

Поскольку TableView и использовать CollectionView в функции

dequeueReusableCell(withReuseIdentifier: for indexPath:) при настройке новой ячейки, что скор делает под столом, это использовать ячейку, которая находится вне экрана, чтобы помочь памяти вашего телефона и, возможно, эта ячейка уже имеет набор изображений, и вам придется обрабатывать этот случай.

Предлагаю вам ознакомиться с методом «prepareCellForReuse», в этом случае мне кажется, что вам нужно установить атрибут imageView.image в ноль.

Я уверен, что он решит вашу проблему или даст вам правильное направление, но если это не сработает, сообщите мне, и я постараюсь вам помочь.

Лучшие результаты.

+0

Я пробовал это, но кажется, что он ничего не делает. –

0

Использование SDWebImage и добавить шаблон изображения:

cell.imageView.sd_setImage(with: URL(string: "http://www.domain.com/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png")) 
+0

У меня нет доступа к URL для каждого файла, у меня есть только файл. Есть ли другая библиотека, которая не требует URL? –

Смежные вопросы