Reputation: 1365
I have an app like instagram that display photos in a tableView. When the network is slow, image are re used in wrong cells and my dowload indicator label is also reused in wrong cells as i scroll fast.
I tried to use async image loading but can't optimize it.
Here is my cellForRowAtIndexPath method :
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:WallTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as WallTableViewCell
if indexPath.section == timeLineData.count - 1 {
println("load more pics")
loadPost()
}
cell.tag = indexPath.row
// timeLineData is my data array
if timeLineData.count != 0 {
let userPost = timeLineData.objectAtIndex(indexPath.section) as PFObject
cell.commentButton.tag = indexPath.section
// check if image is in the cache
if let imagePostedCache: AnyObject = self.imageCache.objectForKey(userPost.objectId){
dispatch_async(dispatch_get_main_queue(), {
if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) as? WallTableViewCell {
cell.imagePosted.image = imagePostedCache as? UIImage
cell.downloadProgressLabel.hidden = true
}
})
}
// if it is not in the cache get the image from Parse
else if let imagesPost:PFFile = userPost["imageFile"] as? PFFile {
cell.imagePosted.image = nil
cell.downloadProgressLabel.hidden = false
imagesPost.getDataInBackgroundWithBlock({ (imageData:NSData!, error :NSError!) -> Void in
if !(error != nil) {
let image:UIImage = UIImage(data: imageData)!
// add image to the cache
self.imageCache.setObject( image , forKey: userPost.objectId)
// display image in the cell
dispatch_async(dispatch_get_main_queue(), {
if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) as? WallTableViewCell {
cell.imagePosted.image = image as UIImage
}
})
}
else {
println("error")
}
}, progressBlock: { (progressStatus :Int32) -> Void in
cell.downloadProgressLabel.text = "\(progressStatus) %"
if progressStatus == 100 {
cell.downloadProgressLabel.text = ""
}
})
}
// Define description
if cell.tag == indexPath.row {
cell.brandLabel.text = userPost["photoText"] as? String
}
}
return cell
}
Here is my custom cell :
import UIKit
import QuartzCore
class WallTableViewCell: UITableViewCell {
@IBOutlet var downloadProgressLabel: UILabel!
@IBOutlet var commentButton: UIButton!
@IBOutlet var imagePosted: UIImageView!
@IBOutlet var brandLabel: UILabel!
}
Upvotes: 0
Views: 1691
Reputation: 1538
Try using SDWebImages . It will handle images for your application properly .
Upvotes: 0
Reputation: 566
WallTableViewCell
import UIKit
import QuartzCore
class WallTableViewCell: UITableViewCell
{
var isDownloadingInProgress
@IBOutlet var downloadProgressLabel: UILabel!
@IBOutlet var commentButton: UIButton!
@IBOutlet var imagePosted: UIImageView!
@IBOutlet var brandLabel: UILabel!
func updateCellWithUserPost(userPost: PFObject)
{
if let imagePostedCache: AnyObject = self.imageCache.objectForKey(userPost.objectId)
{
self.imagePosted.image = imagePostedCache as? UIImage
self.downloadProgressLabel.hidden = true
}
else if let imagesPost:PFFile = userPost["imageFile"] as? PFFile
{
self.imagePosted.image = nil
self.downloadProgressLabel.hidden = false
isDownloadingInProgress = true
imagesPost.getDataInBackgroundWithBlock({ (imageData:NSData!, error :NSError!) -> Void in
isDownloadingInProgress = false
if !(error != nil)
{
let image:UIImage = UIImage(data: imageData)!
self.imageCache.setObject( image , forKey: userPost.objectId)
self.imagePosted.image = image as UIImage
}
else
{
println("Error while downloading image")
}
}, progressBlock: { (progressStatus :Int32) -> Void in
self.downloadProgressLabel.text = "\(progressStatus) %"
if progressStatus == 100
{
cell.downloadProgressLabel.text = ""
}
})
}
}
}
cellForRowAtIndexPath method
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:WallTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as WallTableViewCell
let userPost = timeLineData.objectAtIndex(indexPath.section) as PFObject
if (!cell.isDownloadingInProgress)
cell.updateCellWithUserPost(userPost)
return cell
}
Note: I don't know Swift too much as I am a pure Objective-C programmer. Let me know if you have any questions regarding the answer
Upvotes: 1