Home > OS >  Image duplication in UITableViewCell in Swift
Image duplication in UITableViewCell in Swift

Time:09-17

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

  1. instal pod pod 'SDWebImage'

  2. After successfully istallation. Open your table view controller class.

  3. import SDWebImage

  4. 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")
    }
}
  • Related