将异步 Gif 加载到滚动的 UICollectionView
Loading Aync Gifs to Scrolling CollectionView
我从 Giphy API
returns 正确获取的 gif,实际上使用 SwiftGif
.
正确加载到 uicollectionview
问题仅在我立即滚动时出现,uicollectionview
加载重复的 gif 或索引不正确的 gif。我知道这可能是延迟渲染 gif 和将 gif 加载到单元格的时间问题。
任何指导将不胜感激,因为异步操作是我仍然不熟悉的东西..
如果下面的代码中有任何标志,特别是为了支持 speed/memory 用法,我们将不胜感激任何处理 gif 的最佳实践。
我试过进行各种检查,比如查看最初传递的 gif url 在加载时是否相同,以及每次触发 cellForItemAt
时都将图像设置为 nil,但无济于事。找不到也能明确解决此问题的现有讨论帖。
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var gifCollectionView: UICollectionView!
var gifUrls: [String] = []
var gifImages: [String: UIImage] = [:]
func fetchGiphs() {
let op = GiphyCore.shared.search("dogs", media: .sticker) { (response, error) in
guard error == nil else {
print("Giphy Fetch Error: ", error)
return
}
if let response = response, let data = response.data, let pagination = response.pagination {
for result in data {
if let urlStr = result.images?.downsized?.gifUrl {
self.gifUrls.append(urlStr)
}
}
if !self.gifUrls.isEmpty {
DispatchQueue.main.async {
self.gifCollectionView.reloadData()
}
}
} else {
print("No Results Found")
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return gifUrls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! GifCell
let passedUrlString = gifUrls[indexPath.item]
cell.imageView.image = nil
if let image = gifImages[gifUrls[indexPath.item]] {
DispatchQueue.main.async {
cell.imageView.image = image
cell.activityIndicator.isHidden = true
}
} else {
cell.activityIndicator.isHidden = false
cell.activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
let gifImage = UIImage.gif(url: self.gifUrls[indexPath.item])
DispatchQueue.main.async {
if passedUrlString == self.gifUrls[indexPath.item] {
cell.activityIndicator.stopAnimating()
cell.activityIndicator.isHidden = true
cell.imageView.image = gifImage
self.gifImages[self.gifUrls[indexPath.item]] = gifImage
}
}
}
}
return cell
}
}
class GifCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
}
如您所知,当图像加载完成后,单元格可能会被重复使用。
您需要检查它是否被重复使用。您的 passedUrlString == self.gifUrls[indexPath.item]
不适用于此目的。
也许,为每个单元格提供唯一 ID 会奏效:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! GifCell
let uniqueId = Int.random(in: Int.min...Int.max) //<-practically unique
cell.tag = uniqueId //<-
cell.imageView.image = nil
if let image = gifImages[gifUrls[indexPath.item]] {
cell.imageView.image = image
cell.activityIndicator.isHidden = true
} else {
cell.activityIndicator.isHidden = false
cell.activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
let gifImage = UIImage.gif(url: self.gifUrls[indexPath.item])
DispatchQueue.main.async {
if cell.tag == uniqueId { //<- check `cell.tag` is not changed
cell.activityIndicator.stopAnimating()
cell.activityIndicator.isHidden = true
cell.imageView.image = gifImage
self.gifImages[self.gifUrls[indexPath.item]] = gifImage
}
}
}
}
return cell
}
假设您没有将 tag
用于其他目的。
请尝试。
我从 Giphy API
returns 正确获取的 gif,实际上使用 SwiftGif
.
uicollectionview
问题仅在我立即滚动时出现,uicollectionview
加载重复的 gif 或索引不正确的 gif。我知道这可能是延迟渲染 gif 和将 gif 加载到单元格的时间问题。
任何指导将不胜感激,因为异步操作是我仍然不熟悉的东西..
如果下面的代码中有任何标志,特别是为了支持 speed/memory 用法,我们将不胜感激任何处理 gif 的最佳实践。
我试过进行各种检查,比如查看最初传递的 gif url 在加载时是否相同,以及每次触发 cellForItemAt
时都将图像设置为 nil,但无济于事。找不到也能明确解决此问题的现有讨论帖。
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var gifCollectionView: UICollectionView!
var gifUrls: [String] = []
var gifImages: [String: UIImage] = [:]
func fetchGiphs() {
let op = GiphyCore.shared.search("dogs", media: .sticker) { (response, error) in
guard error == nil else {
print("Giphy Fetch Error: ", error)
return
}
if let response = response, let data = response.data, let pagination = response.pagination {
for result in data {
if let urlStr = result.images?.downsized?.gifUrl {
self.gifUrls.append(urlStr)
}
}
if !self.gifUrls.isEmpty {
DispatchQueue.main.async {
self.gifCollectionView.reloadData()
}
}
} else {
print("No Results Found")
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return gifUrls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! GifCell
let passedUrlString = gifUrls[indexPath.item]
cell.imageView.image = nil
if let image = gifImages[gifUrls[indexPath.item]] {
DispatchQueue.main.async {
cell.imageView.image = image
cell.activityIndicator.isHidden = true
}
} else {
cell.activityIndicator.isHidden = false
cell.activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
let gifImage = UIImage.gif(url: self.gifUrls[indexPath.item])
DispatchQueue.main.async {
if passedUrlString == self.gifUrls[indexPath.item] {
cell.activityIndicator.stopAnimating()
cell.activityIndicator.isHidden = true
cell.imageView.image = gifImage
self.gifImages[self.gifUrls[indexPath.item]] = gifImage
}
}
}
}
return cell
}
}
class GifCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
}
如您所知,当图像加载完成后,单元格可能会被重复使用。
您需要检查它是否被重复使用。您的 passedUrlString == self.gifUrls[indexPath.item]
不适用于此目的。
也许,为每个单元格提供唯一 ID 会奏效:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! GifCell
let uniqueId = Int.random(in: Int.min...Int.max) //<-practically unique
cell.tag = uniqueId //<-
cell.imageView.image = nil
if let image = gifImages[gifUrls[indexPath.item]] {
cell.imageView.image = image
cell.activityIndicator.isHidden = true
} else {
cell.activityIndicator.isHidden = false
cell.activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
let gifImage = UIImage.gif(url: self.gifUrls[indexPath.item])
DispatchQueue.main.async {
if cell.tag == uniqueId { //<- check `cell.tag` is not changed
cell.activityIndicator.stopAnimating()
cell.activityIndicator.isHidden = true
cell.imageView.image = gifImage
self.gifImages[self.gifUrls[indexPath.item]] = gifImage
}
}
}
}
return cell
}
假设您没有将 tag
用于其他目的。
请尝试。