2017-02-05 3 views
0

DropBoxのAPIを使用してイメージをダウンロードし、コレクションビューに表示しています。ユーザーがスクロールすると、イメージはセルから消え、別のイメージがロードされるか、新しいイメージが再ロードされ、セル内のイメージが置き換えられます。これを防ぐ方法を教えてください。私はSDWebImageを使ってみましたが、これは正しい順序でイメージを保持しますが、画面からスクロールするたびにイメージが消えて再ロードされます。また、URLからではなく、直接画像をダウンロードしていますので、SDWebImageを使用できるように一括作業を書く必要はありません。UIコレクションビューでスクロールすると、セルが間違ったイメージをリロードする

私は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

:ここ は新しいcellForItemAtコードです。 – luk2302

答えて

0

が、私はそれを修正しました。 cellForItemAt funcにcell image = nilを設定し、ダウンロードが完了する前にユーザーが画面をスクロールした場合にイメージ要求をキャンセルする必要がありました。 cellIndex == indexPath.item`は** `true`を常に**であれば`

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

新しいセルを構成するときにテーブルビューのとCollectionViewの使用

dequeueReusableCell(withReuseIdentifier: for indexPath:)関数は、テーブルの下に何迅速出ているセルを使用しているためあなたの携帯電話のメモリを助けるために、おそらくそのセルにはすでに画像が設定されているので、このケースを処理する必要があります。

"prepareCellForReuse"というメソッドを見ることをお勧めします。この場合は、imageView.image属性をnilに設定する必要があります。

私はそれがあなたの問題を解決するか、あなたに正しい方向を与えるとはかなり確信していますが、それがうまくいかない場合は教えてくださいと私はあなたを助けようとします。

ベストセラー

+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を必要としない別のライブラリがありますか? –

関連する問題