如何使用NSCache从UICollectionView中的Web服务器异步加载图像
使用NScache从UICollectionView中的Web服务器加载图像时,我遇到一些问题.
I have some issues when loading images from a web-server in UICollectionView using NScache.
问题:
图像显示不正确:
- 有时它们未显示在相应的单元格中
或
- 图像在滚动变化
情况:
-
我有3个数组,可以从Web服务器的viewDidLoad()函数中正确加载.这些数组是:vPrice,vTitle和vImages_api
I have 3 arrays whitch are properly loaded from the web-server in function viewDidLoad(). These arrays are: vPrice, vTitle and vImages_api
我对单元格的自定义类有:
my custom class for cell have:
-
价格标签:cell.lblPrice
label for price: cell.lblPrice
标题标签:cell.lblTitle
label for title: cell.lblTitle
图片:cell.imgPicture
image: cell.imgPicture
我相信问题出在函数func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath)-> UICollectionViewCell
I belive that the problem is in function func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
这可能与我使用NSCache的方式或我使用DispatchQueue的方式有关.
It could be related either to the way I use NSCache or to the way I use and when I use DispatchQueue.
代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as! clsCustomCell
cell.lblPrice.text = vPrice[indexPath.item]
cell.lblTitle.text = vTitle[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 0.5
DispatchQueue.global(qos: .userInitiated).async {
//background thread
let ImageString = self.vImages_api[indexPath.item]
let imageUrl = URL(string: ImageString)
let imageData = NSData(contentsOf: imageUrl!)
// main thread to update the UI
DispatchQueue.main.async {
let key1 = self.vImages_api[indexPath.item] as AnyObject
//if i saved allready my image in cache, then i will load my image from cache
if let imageFromCache = self.objCache.object(forKey: key1){
cell.imgPicture.image = imageFromCache as! UIImage
}
else{//if my image is not in cache ......
if imageData != nil {
let myPicture = UIImage(data: imageData! as Data)
cell.imgPicture.image = myPicture
//save my image in cache
self.objCache.setObject(myPicture!, forKey: ImageString as AnyObject)
}
}
}
}
return cell
}
编辑后的代码-版本II:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "MyCustomCell", for: indexPath) as! clsCustomCell
cell.lblPret.text = vPrice[indexPath.item]
cell.lblTitlu.text = vTitle[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 0.5
let key1 = self.vImages_api[indexPath.item] as AnyObject
if let imageFromCache = self.objCache.object(forKey: key1){
cell.imgPicture.image = imageFromCache as! UIImage
}else{
DispatchQueue.global(qos: .background).async {
let ImageString = self.vImages_api[indexPath.item]
let imageUrl = URL(string: ImageString)
let imageData = NSData(contentsOf: imageUrl!)
let myPicture = UIImage(data: imageData! as Data)
self.objCache.setObject(poza!, forKey: ImageString as AnyObject)
DispatchQueue.main.async {
if imageData != nil {
cell.imgPicture.image = myPicture
}
}
}
}
return cell
}
已编辑的代码-版本III
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "celula_custom", for: indexPath) as! clsCustomCell
cell.lblPret.text = vPrice[indexPath.item]
cell.lblTitlu.text = vTitle[indexPath.item]
NKPlaceholderImage(image: UIImage(named: "loading"), imageView: cell.imgPicture, imgUrl: self.vImages_api[indexPath.item]
) { (image11) in
cell.imgPicture.image = image11
}
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 0.5
return cell
}
尝试此代码为工作代码(快速键4).
Try this one it's Working code (Swift 4).
func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){
if image != nil && imageView != nil {
imageView!.image = image!
}
var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
urlcatch = documentpath + "/" + "\(urlcatch)"
let image = UIImage(contentsOfFile:urlcatch)
if image != nil && imageView != nil
{
imageView!.image = image!
compate(image)
}else{
if let url = URL(string: imgUrl){
DispatchQueue.global(qos: .background).async {
() -> Void in
let imgdata = NSData(contentsOf: url)
DispatchQueue.main.async {
() -> Void in
imgdata?.write(toFile: urlcatch, atomically: true)
let image = UIImage(contentsOfFile:urlcatch)
compate(image)
if image != nil {
if imageView != nil {
imageView!.image = image!
}
}
}
}
}
}
}
像这样使用:
// Here imgPicture = your imageView and UIImage(named: "placeholder") is Display image brfore download actual image.
imgPicture.image = nil
NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }