I have searched through the internet and found solutions like, to use prepareForReuse() and making the imageview = nil at the cellForRowAt. I have tried both these methods but it does not work. Please help me to figure out how to prevent image duplication in UITableViewCell
Below are the code that I have tried previously,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: EmployeeTableViewCell.self), for: indexPath) as! EmployeeTableViewCell
cell.onBindCell(employee: directoryPresenter!.getEmployeeItem(position: indexPath.row))
directoryPresenter!.getProfileImage(id: (directoryPresenter!.getEmployeeItem(position: indexPath.row).employeeID)) { image in
if let image = image {
cell.profileImage.image = image
} else {
// Default image or nil
cell.profileImage.image = UIImage(named: "placeholder_profile_male")
}
}
cell.actionCallBack = self
return cell
}
Below is the code that I have added inside the custom table view cell class,
@IBOutlet weak var profileImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func prepareForReuse() {
super.prepareForReuse()
self.profileImage.image = nil
}
CodePudding user response:
Your image fetched from closure, you should set its default image before block callback, like this:
// Default image
cell.profileImage.image = UIImage(named: "placeholder_profile_male")
// fetch employee image
directoryPresenter!.getProfileImage(id: (directoryPresenter!.getEmployeeItem(position: indexPath.row).employeeID)) { image in
// handle async fetching task
// call main queue to update UI
DispatchQueue.main.async {
if let image = image {
cell.profileImage.image = image
}
}
}
If your image is fetched from url, here is the idea to let URLSession handling the job:
cell.profileImage.image = UIImage(named: "placeholder_profile_male")
let url = URL(string: urlString)!
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
print("Error: \(error)")
return
}
let image = UIImage.init(data: data!)
DispatchQueue.main.async {
cell.profileImage.image = image
}
}.resume()
CodePudding user response:
Best way to use image and placeholder. Use SDWebImage
Steps
instal pod
pod 'SDWebImage'
After successfully istallation. Open your table view controller class.
import SDWebImage
In Cell for row at index path
// this is a activity indicator and automatically work on your image
cell.yourImageName.sd_imageIndicator = SDWebImageActivityIndicator.grayLarge
cell.yourImageName.sd_setImage(with: URL(string: yourImageInString),
placeholderImage: UIImage(named: "yourPlaceHolderImageName"))
CodePudding user response:
If a UITableViewCell object has a reuse identifier, the table view invokes this method just before returning the object from the UITableView method dequeueReusableCell(withIdentifier:). To avoid potential performance issues, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView(_:cellForRowAt:) should always reset all content when reusing a cell.
The table view doesn’t call this method if the cell object doesn’t have an associated reuse identifier, or if you use reconfigureRows(at:) to update the contents of an existing cell.
If you override this method, you must be sure to invoke the superclass implementation.
Visit https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse
try this as well
cell.profileImage.image = nil
directoryPresenter!.getProfileImage(id: (directoryPresenter!.getEmployeeItem(position: indexPath.row).employeeID)) { image in
if let image = image {
cell.profileImage.image = image
} else {
// Default image or nil
cell.profileImage.image = UIImage(named: "placeholder_profile_male")
}
}