0

I change the height of a UIImageView inside UITableViewCell programmatically.So when there is an image url, height is 100.0 and when image url is nil, height is 0.0 . This is the code i use in my tableViewCell class :

func setConstraints(_height:CGFloat){
    self.commentImage.addConstraint(NSLayoutConstraint(item: self.commentImage,attribute: .height,relatedBy: .equal,toItem: self.commentImage,attribute: .width,multiplier: _height / 287.0,constant: 0))
    self.commentImage.updateConstraints()
    self.commentImage.layoutIfNeeded()
}

if let img = comment.image {
        let imgUrl = URL(string: img)
        self.commentImage.sd_setImage(with: imgUrl, placeholderImage: UIImage(named: "PlaceHolder Shop"))
        setConstraints(_height: 100.0)
    }else {
        self.commentImage.image = nil
        setConstraints(_height: 0.0)
    }

Now the problem is that when I scroll the tableview, some of the rows that has no image url, get the height of 100.0 for UIImageView, which leaves a blank area, And if I scroll tableView very fast, sometimes the images in rows are gone.

What should I do to solve this problem?What am I missing here?

2
  • Add a stackview in cell and add image view as subview. Hide & show the image view based on the url. It will automatically adjust constraints. Commented Nov 28, 2017 at 12:27
  • well this worked perfect.Thanks man. Commented Dec 2, 2017 at 6:46

2 Answers 2

1

CustomTableViewCell with stackview

class CustomTableViewCell: UITableViewCell {

  let titleLbl = UILabel()
  let stackView = UIStackView()
  let imgView = UIImageView()

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
  override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    titleLbl.translatesAutoresizingMaskIntoConstraints = false
    addSubview(titleLbl)

    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.axis = .vertical
    stackView.spacing = 0
    stackView.alignment = .fill
    stackView.distribution = .fill
    addSubview(stackView)

    imgView.translatesAutoresizingMaskIntoConstraints = false
    let imgViewHeight = imgView.heightAnchor.constraint(equalToConstant: 100)
    imgViewHeight.priority = .defaultLow
    imgViewHeight.isActive = true
    imgView.addConstraint(imgViewHeight)

    stackView.addArrangedSubview(imgView)

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[titleLbl]|", options: [], metrics: nil, views: ["titleLbl":titleLbl,"stackView":stackView]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[titleLbl(30)][stackView]|", options: [.alignAllLeading,.alignAllTrailing], metrics: nil, views: ["titleLbl":titleLbl,"stackView":stackView]))
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

}

ViewController with automatic height tableView

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

  @IBOutlet var tableView: UITableView!

  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomCell")
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 130
  }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 15
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomTableViewCell
    cell.titleLbl.text = "Row \(indexPath.row)"
    // set cell.imgView.image
    cell.imgView.isHidden = cell.imageView?.image == nil
    return cell
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

UITableViewCells are recycled. Your setConstraints method is not actually setting the constraints; its adding a new constraint over an over again. To do this correctly you can just set the constraints in Interface builder. Find the height constraint in the size inspector and double click it to select it in the document outline. Option drag from the constraint to your tableViewCell to create an IBOutlet called heightConstraint. Change your code as follows:

func setConstraints(_height:CGFloat){
    heightConstraint.constant = height
    commentImage.setNeedsLayout()
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.